blob: f233eed3952617cb6ec9a14b25e05258d7e3b853 [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>
Stefan Reinauer138be832010-02-27 01:50:21 +000019#include "i82801dx.h"
Ronald G. Minnich182615d2004-08-24 16:20:46 +000020
Elyes HAOUAS66faf0c2018-05-13 13:32:56 +020021void i82801dx_enable(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000022{
Steven J. Magnani75573312005-09-21 13:49:44 +000023 unsigned int index = 0;
24 uint8_t bHasDisableBit = 0;
25 uint16_t cur_disable_mask, new_disable_mask;
Ronald G. Minnich182615d2004-08-24 16:20:46 +000026
Stefan Reinauer8702ab52010-03-14 17:01:08 +000027// all 82801dbm devices are in bus 0
28 unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc
Kyösti Mälkkie7377552018-06-21 16:20:55 +030029 struct device *lpc_dev = pcidev_path_on_root(devfn); // 0
Steven J. Magnani75573312005-09-21 13:49:44 +000030 if (!lpc_dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000031 return;
Steven J. Magnani75573312005-09-21 13:49:44 +000032
33 // Calculate disable bit position for specified device:function
34 // NOTE: For ICH-4, only the following devices can be disabled:
Stefan Reinauer14e22772010-04-27 06:56:47 +000035 // D31: F0, F1, F3, F5, F6,
Stefan Reinauer8702ab52010-03-14 17:01:08 +000036 // D29: F0, F1, F2, F7
Steven J. Magnani75573312005-09-21 13:49:44 +000037
Stefan Reinauer8702ab52010-03-14 17:01:08 +000038 if (PCI_SLOT(dev->path.pci.devfn) == 31) {
39 index = PCI_FUNC(dev->path.pci.devfn);
Steven J. Magnani75573312005-09-21 13:49:44 +000040
41 switch (index) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000042 case 0:
43 case 1:
44 case 3:
45 case 5:
46 case 6:
Steven J. Magnani75573312005-09-21 13:49:44 +000047 bHasDisableBit = 1;
Stefan Reinauer8702ab52010-03-14 17:01:08 +000048 break;
49
50 default:
51 break;
52 };
53
54 if (index == 0)
55 index = 14; // D31:F0 bit is an exception
56
57 } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
58 index = 8 + PCI_FUNC(dev->path.pci.devfn);
59
60 if ((PCI_FUNC(dev->path.pci.devfn) < 3)
61 || (PCI_FUNC(dev->path.pci.devfn) == 7))
62 bHasDisableBit = 1;
63 }
Steven J. Magnani75573312005-09-21 13:49:44 +000064
65 if (bHasDisableBit) {
66 cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
Stefan Reinauer8702ab52010-03-14 17:01:08 +000067 new_disable_mask = cur_disable_mask & ~(1 << index); // enable it
Steven J. Magnani75573312005-09-21 13:49:44 +000068 if (!dev->enabled) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000069 new_disable_mask |= (1 << index); // disable it
Steven J. Magnani75573312005-09-21 13:49:44 +000070 }
71 if (new_disable_mask != cur_disable_mask) {
72 pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000073 }
74 }
Ronald G. Minnich182615d2004-08-24 16:20:46 +000075}
76
Stefan Reinauer138be832010-02-27 01:50:21 +000077struct chip_operations southbridge_intel_i82801dx_ops = {
78 CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge")
Stefan Reinauer8702ab52010-03-14 17:01:08 +000079 .enable_dev = i82801dx_enable,
Ronald G. Minnich182615d2004-08-24 16:20:46 +000080};