2352723935b171a3b584cf88e3c54c67cc1aa957
[coreboot.git] / src / southbridge / intel / i82801bx / i82801bx.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2005 Digital Design Corporation
5  * (Written by Steven J. Magnani <steve@digidescorp.com> for Digital Design)
6  * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21  */
22
23 #include <console/console.h>
24 #include <device/device.h>
25 #include <device/pci.h>
26 #include "i82801bx.h"
27
28 void i82801bx_enable(device_t dev)
29 {
30         unsigned int index = 0;
31         uint16_t cur_disable_mask, new_disable_mask;
32
33         /* All 82801xx devices should be on 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         /* We're going to assume, perhaps incorrectly, that if a function
40          * exists it can be disabled. Workarounds for ICH variants that don't
41          * follow this should be done by checking the device ID.
42          */
43         if (PCI_SLOT(dev->path.pci.devfn) == 31) {
44                 index = PCI_FUNC(dev->path.pci.devfn);
45         } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
46                 index = 8 + PCI_FUNC(dev->path.pci.devfn);
47         }
48
49         /* Function 0 is a bit of an exception. */
50         if (index == 0) {
51                 index = 14;
52         }
53
54         cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
55         new_disable_mask = cur_disable_mask & ~(1 << index); /* Enable it. */
56         if (!dev->enabled) {
57                 new_disable_mask |= (1 << index); /* Disable it, if desired. */
58         }
59         if (new_disable_mask != cur_disable_mask) {
60                 pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
61         }
62 }
63
64 struct chip_operations southbridge_intel_i82801bx_ops = {
65         CHIP_NAME("Intel ICH2 (82801Bx) Series Southbridge")
66         .enable_dev = i82801bx_enable,
67 };