blob: 765bcb258704b7fb6415c3f057fec14cf0be8e6e [file] [log] [blame]
Stefan Reinauer8702ab52010-03-14 17:01:08 +00001/*
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.
Stefan Reinauer8702ab52010-03-14 17:01:08 +000015 */
16
Ronald G. Minnich182615d2004-08-24 16:20:46 +000017#include <device/device.h>
18#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020019#include <device/pci_ops.h>
Stefan Reinauer138be832010-02-27 01:50:21 +000020#include "i82801dx.h"
Ronald G. Minnich182615d2004-08-24 16:20:46 +000021
Elyes HAOUAS66faf0c2018-05-13 13:32:56 +020022void i82801dx_enable(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000023{
Steven J. Magnani75573312005-09-21 13:49:44 +000024 unsigned int index = 0;
25 uint8_t bHasDisableBit = 0;
26 uint16_t cur_disable_mask, new_disable_mask;
Ronald G. Minnich182615d2004-08-24 16:20:46 +000027
Stefan Reinauer8702ab52010-03-14 17:01:08 +000028// all 82801dbm devices are in bus 0
29 unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc
Kyösti Mälkkie7377552018-06-21 16:20:55 +030030 struct device *lpc_dev = pcidev_path_on_root(devfn); // 0
Steven J. Magnani75573312005-09-21 13:49:44 +000031 if (!lpc_dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000032 return;
Steven J. Magnani75573312005-09-21 13:49:44 +000033
34 // Calculate disable bit position for specified device:function
35 // NOTE: For ICH-4, only the following devices can be disabled:
Stefan Reinauer14e22772010-04-27 06:56:47 +000036 // D31: F0, F1, F3, F5, F6,
Stefan Reinauer8702ab52010-03-14 17:01:08 +000037 // D29: F0, F1, F2, F7
Steven J. Magnani75573312005-09-21 13:49:44 +000038
Stefan Reinauer8702ab52010-03-14 17:01:08 +000039 if (PCI_SLOT(dev->path.pci.devfn) == 31) {
40 index = PCI_FUNC(dev->path.pci.devfn);
Steven J. Magnani75573312005-09-21 13:49:44 +000041
42 switch (index) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000043 case 0:
44 case 1:
45 case 3:
46 case 5:
47 case 6:
Steven J. Magnani75573312005-09-21 13:49:44 +000048 bHasDisableBit = 1;
Stefan Reinauer8702ab52010-03-14 17:01:08 +000049 break;
50
51 default:
52 break;
53 };
54
55 if (index == 0)
56 index = 14; // D31:F0 bit is an exception
57
58 } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
59 index = 8 + PCI_FUNC(dev->path.pci.devfn);
60
61 if ((PCI_FUNC(dev->path.pci.devfn) < 3)
62 || (PCI_FUNC(dev->path.pci.devfn) == 7))
63 bHasDisableBit = 1;
64 }
Steven J. Magnani75573312005-09-21 13:49:44 +000065
66 if (bHasDisableBit) {
67 cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
Stefan Reinauer8702ab52010-03-14 17:01:08 +000068 new_disable_mask = cur_disable_mask & ~(1 << index); // enable it
Steven J. Magnani75573312005-09-21 13:49:44 +000069 if (!dev->enabled) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000070 new_disable_mask |= (1 << index); // disable it
Steven J. Magnani75573312005-09-21 13:49:44 +000071 }
72 if (new_disable_mask != cur_disable_mask) {
73 pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000074 }
75 }
Ronald G. Minnich182615d2004-08-24 16:20:46 +000076}
77
Stefan Reinauer138be832010-02-27 01:50:21 +000078struct chip_operations southbridge_intel_i82801dx_ops = {
79 CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge")
Stefan Reinauer8702ab52010-03-14 17:01:08 +000080 .enable_dev = i82801dx_enable,
Ronald G. Minnich182615d2004-08-24 16:20:46 +000081};