blob: f01064c0490ac47cd9e925c42cb931a2f8a845ff [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Stefan Reinauer8702ab52010-03-14 17:01:08 +00003
Ronald G. Minnich182615d2004-08-24 16:20:46 +00004#include <device/device.h>
5#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02006#include <device/pci_ops.h>
Stefan Reinauer138be832010-02-27 01:50:21 +00007#include "i82801dx.h"
Ronald G. Minnich182615d2004-08-24 16:20:46 +00008
Elyes HAOUAS66faf0c2018-05-13 13:32:56 +02009void i82801dx_enable(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000010{
Steven J. Magnani75573312005-09-21 13:49:44 +000011 unsigned int index = 0;
12 uint8_t bHasDisableBit = 0;
13 uint16_t cur_disable_mask, new_disable_mask;
Ronald G. Minnich182615d2004-08-24 16:20:46 +000014
Stefan Reinauer8702ab52010-03-14 17:01:08 +000015// all 82801dbm devices are in bus 0
16 unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc
Kyösti Mälkkie7377552018-06-21 16:20:55 +030017 struct device *lpc_dev = pcidev_path_on_root(devfn); // 0
Steven J. Magnani75573312005-09-21 13:49:44 +000018 if (!lpc_dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000019 return;
Steven J. Magnani75573312005-09-21 13:49:44 +000020
21 // Calculate disable bit position for specified device:function
22 // NOTE: For ICH-4, only the following devices can be disabled:
Stefan Reinauer14e22772010-04-27 06:56:47 +000023 // D31: F0, F1, F3, F5, F6,
Stefan Reinauer8702ab52010-03-14 17:01:08 +000024 // D29: F0, F1, F2, F7
Steven J. Magnani75573312005-09-21 13:49:44 +000025
Stefan Reinauer8702ab52010-03-14 17:01:08 +000026 if (PCI_SLOT(dev->path.pci.devfn) == 31) {
27 index = PCI_FUNC(dev->path.pci.devfn);
Steven J. Magnani75573312005-09-21 13:49:44 +000028
29 switch (index) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000030 case 0:
31 case 1:
32 case 3:
33 case 5:
34 case 6:
Steven J. Magnani75573312005-09-21 13:49:44 +000035 bHasDisableBit = 1;
Stefan Reinauer8702ab52010-03-14 17:01:08 +000036 break;
37
38 default:
39 break;
40 };
41
42 if (index == 0)
43 index = 14; // D31:F0 bit is an exception
44
45 } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
46 index = 8 + PCI_FUNC(dev->path.pci.devfn);
47
48 if ((PCI_FUNC(dev->path.pci.devfn) < 3)
49 || (PCI_FUNC(dev->path.pci.devfn) == 7))
50 bHasDisableBit = 1;
51 }
Steven J. Magnani75573312005-09-21 13:49:44 +000052
53 if (bHasDisableBit) {
54 cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
Stefan Reinauer8702ab52010-03-14 17:01:08 +000055 new_disable_mask = cur_disable_mask & ~(1 << index); // enable it
Steven J. Magnani75573312005-09-21 13:49:44 +000056 if (!dev->enabled) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000057 new_disable_mask |= (1 << index); // disable it
Steven J. Magnani75573312005-09-21 13:49:44 +000058 }
59 if (new_disable_mask != cur_disable_mask) {
60 pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000061 }
62 }
Ronald G. Minnich182615d2004-08-24 16:20:46 +000063}
64
Stefan Reinauer138be832010-02-27 01:50:21 +000065struct chip_operations southbridge_intel_i82801dx_ops = {
66 CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge")
Stefan Reinauer8702ab52010-03-14 17:01:08 +000067 .enable_dev = i82801dx_enable,
Ronald G. Minnich182615d2004-08-24 16:20:46 +000068};