282ccfd2473acc894f7bad6a8d2b5d98b5ca6585
[coreboot.git] / src / southbridge / intel / i82801dx / i82801dx.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004 Ron G. Minnich
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; version 2 of
9  * 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <console/console.h>
22 #include <device/device.h>
23 #include <device/pci.h>
24 #include <device/pci_ids.h>
25 #include "i82801dx.h"
26
27 void i82801dx_enable(device_t dev)
28 {
29         unsigned int index = 0;
30         uint8_t bHasDisableBit = 0;
31         uint16_t cur_disable_mask, new_disable_mask;
32
33 //      all 82801dbm devices are in bus 0
34         unsigned int devfn = PCI_DEVFN(0x1f, 0);        // lpc
35         device_t lpc_dev = dev_find_slot(0, devfn);     // 0
36         if (!lpc_dev)
37                 return;
38
39         // Calculate disable bit position for specified device:function
40         // NOTE: For ICH-4, only the following devices can be disabled:
41         //               D31: F0, F1, F3, F5, F6, 
42         //               D29: F0, F1, F2, F7
43
44         if (PCI_SLOT(dev->path.pci.devfn) == 31) {
45                 index = PCI_FUNC(dev->path.pci.devfn);
46
47                 switch (index) {
48                 case 0:
49                 case 1:
50                 case 3:
51                 case 5:
52                 case 6:
53                         bHasDisableBit = 1;
54                         break;
55
56                 default:
57                         break;
58                 };
59
60                 if (index == 0)
61                         index = 14;     // D31:F0 bit is an exception
62
63         } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
64                 index = 8 + PCI_FUNC(dev->path.pci.devfn);
65
66                 if ((PCI_FUNC(dev->path.pci.devfn) < 3)
67                     || (PCI_FUNC(dev->path.pci.devfn) == 7))
68                         bHasDisableBit = 1;
69         }
70
71         if (bHasDisableBit) {
72                 cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
73                 new_disable_mask = cur_disable_mask & ~(1 << index);    // enable it
74                 if (!dev->enabled) {
75                         new_disable_mask |= (1 << index);       // disable it
76                 }
77                 if (new_disable_mask != cur_disable_mask) {
78                         pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
79                 }
80         }
81 }
82
83 struct chip_operations southbridge_intel_i82801dx_ops = {
84         CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge")
85             .enable_dev = i82801dx_enable,
86 };