blob: 921cb1c8aa6ff44260d15fbf6af803df47419302 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer8702ab52010-03-14 17:01:08 +00002
Ronald G. Minnich182615d2004-08-24 16:20:46 +00003#include <device/device.h>
4#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Stefan Reinauer138be832010-02-27 01:50:21 +00006#include "i82801dx.h"
Ronald G. Minnich182615d2004-08-24 16:20:46 +00007
Elyes HAOUAS66faf0c2018-05-13 13:32:56 +02008void i82801dx_enable(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +00009{
Steven J. Magnani75573312005-09-21 13:49:44 +000010 unsigned int index = 0;
11 uint8_t bHasDisableBit = 0;
12 uint16_t cur_disable_mask, new_disable_mask;
Ronald G. Minnich182615d2004-08-24 16:20:46 +000013
Stefan Reinauer8702ab52010-03-14 17:01:08 +000014// all 82801dbm devices are in bus 0
15 unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc
Kyösti Mälkkie7377552018-06-21 16:20:55 +030016 struct device *lpc_dev = pcidev_path_on_root(devfn); // 0
Steven J. Magnani75573312005-09-21 13:49:44 +000017 if (!lpc_dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000018 return;
Steven J. Magnani75573312005-09-21 13:49:44 +000019
20 // Calculate disable bit position for specified device:function
21 // NOTE: For ICH-4, only the following devices can be disabled:
Stefan Reinauer14e22772010-04-27 06:56:47 +000022 // D31: F0, F1, F3, F5, F6,
Stefan Reinauer8702ab52010-03-14 17:01:08 +000023 // D29: F0, F1, F2, F7
Steven J. Magnani75573312005-09-21 13:49:44 +000024
Stefan Reinauer8702ab52010-03-14 17:01:08 +000025 if (PCI_SLOT(dev->path.pci.devfn) == 31) {
26 index = PCI_FUNC(dev->path.pci.devfn);
Steven J. Magnani75573312005-09-21 13:49:44 +000027
28 switch (index) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000029 case 0:
30 case 1:
31 case 3:
32 case 5:
33 case 6:
Steven J. Magnani75573312005-09-21 13:49:44 +000034 bHasDisableBit = 1;
Stefan Reinauer8702ab52010-03-14 17:01:08 +000035 break;
36
37 default:
38 break;
39 };
40
41 if (index == 0)
42 index = 14; // D31:F0 bit is an exception
43
44 } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
45 index = 8 + PCI_FUNC(dev->path.pci.devfn);
46
47 if ((PCI_FUNC(dev->path.pci.devfn) < 3)
48 || (PCI_FUNC(dev->path.pci.devfn) == 7))
49 bHasDisableBit = 1;
50 }
Steven J. Magnani75573312005-09-21 13:49:44 +000051
52 if (bHasDisableBit) {
53 cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
Stefan Reinauer8702ab52010-03-14 17:01:08 +000054 new_disable_mask = cur_disable_mask & ~(1 << index); // enable it
Steven J. Magnani75573312005-09-21 13:49:44 +000055 if (!dev->enabled) {
Stefan Reinauer8702ab52010-03-14 17:01:08 +000056 new_disable_mask |= (1 << index); // disable it
Steven J. Magnani75573312005-09-21 13:49:44 +000057 }
58 if (new_disable_mask != cur_disable_mask) {
59 pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000060 }
61 }
Ronald G. Minnich182615d2004-08-24 16:20:46 +000062}
63
Stefan Reinauer138be832010-02-27 01:50:21 +000064struct chip_operations southbridge_intel_i82801dx_ops = {
65 CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge")
Stefan Reinauer8702ab52010-03-14 17:01:08 +000066 .enable_dev = i82801dx_enable,
Ronald G. Minnich182615d2004-08-24 16:20:46 +000067};