blob: 2707ca6b4337f41075c8b764e919c6740d93bcb4 [file] [log] [blame]
Eric Biederman83b991a2003-10-11 06:20:25 +00001#include <console/console.h>
2#include <device/device.h>
3#include <device/pci.h>
4#include <device/pci_ids.h>
Eric Biederman83b991a2003-10-11 06:20:25 +00005#include "amd8111.h"
6
7void amd8111_enable(device_t dev)
8{
9 device_t lpc_dev;
10 device_t bus_dev;
11 unsigned index;
Eric Biedermandbec2d42004-10-21 10:44:08 +000012 unsigned reg_old, reg;
Yinghai Luf19e2c72004-10-21 01:52:21 +000013
Myles Watson43bb9cd2008-12-18 18:24:11 +000014 /* See if we are on the bus behind the amd8111 pci bridge */
Eric Biederman83b991a2003-10-11 06:20:25 +000015 bus_dev = dev->bus->dev;
Stefan Reinauer14e22772010-04-27 06:56:47 +000016 if ((bus_dev->vendor == PCI_VENDOR_ID_AMD) &&
17 (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI))
Eric Biedermandbec2d42004-10-21 10:44:08 +000018 {
Eric Biederman83b991a2003-10-11 06:20:25 +000019 unsigned devfn;
Stefan Reinauer2b34db82009-02-28 20:10:20 +000020 devfn = bus_dev->path.pci.devfn + (1 << 3);
Eric Biederman83b991a2003-10-11 06:20:25 +000021 lpc_dev = dev_find_slot(bus_dev->bus->secondary, devfn);
Stefan Reinauer2b34db82009-02-28 20:10:20 +000022 index = ((dev->path.pci.devfn & ~7) >> 3) + 8;
23 if (dev->path.pci.devfn == 2) { /* EHCI */
Eric Biedermandbec2d42004-10-21 10:44:08 +000024 index = 16;
25 }
Eric Biederman83b991a2003-10-11 06:20:25 +000026 } else {
27 unsigned devfn;
Stefan Reinauer2b34db82009-02-28 20:10:20 +000028 devfn = (dev->path.pci.devfn) & ~7;
Eric Biederman83b991a2003-10-11 06:20:25 +000029 lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
Stefan Reinauer2b34db82009-02-28 20:10:20 +000030 index = dev->path.pci.devfn & 7;
Eric Biederman83b991a2003-10-11 06:20:25 +000031 }
Eric Biedermandbec2d42004-10-21 10:44:08 +000032 if ((!lpc_dev) || (index >= 17)) {
Eric Biederman83b991a2003-10-11 06:20:25 +000033 return;
34 }
Eric Biederman5cd81732004-03-11 15:01:31 +000035 if ((lpc_dev->vendor != PCI_VENDOR_ID_AMD) ||
Stefan Reinauer14e22772010-04-27 06:56:47 +000036 (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA))
Eric Biedermandbec2d42004-10-21 10:44:08 +000037 {
Eric Biederman5cd81732004-03-11 15:01:31 +000038 uint32_t id;
39 id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
40 if (id != (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8111_ISA << 16))) {
41 return;
42 }
43 }
Yinghai Lu7ccff4e2004-05-05 18:03:42 +000044
Eric Biedermandbec2d42004-10-21 10:44:08 +000045 if (index < 16) {
46 reg = reg_old = pci_read_config16(lpc_dev, 0x48);
47 reg &= ~(1 << index);
48 if (dev->enabled) {
49 reg |= (1 << index);
Yinghai Lu7ccff4e2004-05-05 18:03:42 +000050 }
Eric Biedermandbec2d42004-10-21 10:44:08 +000051 if (reg != reg_old) {
52 pci_write_config16(lpc_dev, 0x48, reg);
53 }
Yinghai Lu7ccff4e2004-05-05 18:03:42 +000054 }
Eric Biedermandbec2d42004-10-21 10:44:08 +000055 else if (index == 16) {
56 reg = reg_old = pci_read_config8(lpc_dev, 0x47);
57 reg &= ~(1 << 7);
58 if (!dev->enabled) {
59 reg |= (1 << 7);
60 }
61 if (reg != reg_old) {
62 pci_write_config8(lpc_dev, 0x47, reg);
63 }
Eric Biederman83b991a2003-10-11 06:20:25 +000064 }
Eric Biederman83b991a2003-10-11 06:20:25 +000065}
66
Eric Biederman7003ba42004-10-16 06:20:29 +000067struct chip_operations southbridge_amd_amd8111_ops = {
Uwe Hermanna7aa29b2006-11-05 18:50:49 +000068 CHIP_NAME("AMD-8111 Southbridge")
Stefan Reinauer14e22772010-04-27 06:56:47 +000069 /* This only called when this device is listed in the
Jason Schildtab327a32005-10-13 00:44:34 +000070 * static device tree.
71 */
Li-Ta Lo9e17d4f2004-05-13 16:49:53 +000072 .enable_dev = amd8111_enable,
Eric Biederman83b991a2003-10-11 06:20:25 +000073};