eric patch
[coreboot.git] / src / southbridge / amd / amd8111 / amd8111_reset.c
1 /* Include this file in the mainboards reset.c
2  */
3 #include <arch/io.h>
4 #include <device/pci_ids.h>
5
6 #define PCI_DEV(BUS, DEV, FN) ( \
7         (((BUS) & 0xFF) << 16) | \
8         (((DEV) & 0x1f) << 11) | \
9         (((FN)  & 0x7) << 8))
10
11 #define PCI_ID(VENDOR_ID, DEVICE_ID) \
12         ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))
13
14 typedef unsigned device_t;
15
16 static void pci_write_config8(device_t dev, unsigned where, unsigned char value)
17 {
18         unsigned addr;
19         addr = dev | where;
20         outl(0x80000000 | (addr & ~3), 0xCF8);
21         outb(value, 0xCFC + (addr & 3));
22 }
23
24 static void pci_write_config32(device_t dev, unsigned where, unsigned value)
25 {
26         unsigned addr;
27         addr = dev | where;
28         outl(0x80000000 | (addr & ~3), 0xCF8);
29         outl(value, 0xCFC);
30 }
31
32 static unsigned pci_read_config32(device_t dev, unsigned where)
33 {
34         unsigned addr;
35         addr = dev | where;
36         outl(0x80000000 | (addr & ~3), 0xCF8);
37         return inl(0xCFC);
38 }
39
40 #define PCI_DEV_INVALID (0xffffffffU)
41 static device_t pci_locate_device(unsigned pci_id, unsigned bus)
42 {
43         device_t dev, last;
44         dev = PCI_DEV(bus, 0, 0);
45         last = PCI_DEV(bus, 31, 7);
46         for(; dev <= last; dev += PCI_DEV(0,0,1)) {
47                 unsigned int id;
48                 id = pci_read_config32(dev, 0);
49                 if (id == pci_id) {
50                         return dev;
51                 }
52         }
53         return PCI_DEV_INVALID;
54 }
55
56 #include "../../../northbridge/amd/amdk8/reset_test.c"
57
58 static unsigned node_link_to_bus(unsigned node, unsigned link)
59 {
60         unsigned reg;
61
62         for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
63                 unsigned config_map;
64                 config_map = pci_read_config32(PCI_DEV(0, 0x18, 1), reg);
65                 if ((config_map & 3) != 3) {
66                         continue;
67                 }
68                 if ((((config_map >> 4) & 7) == node) &&
69                         (((config_map >> 8) & 3) == link)) 
70                 {
71                         return (config_map >> 16) & 0xff;
72                 }
73         }
74         return 0;
75 }
76
77 static void amd8111_hard_reset(unsigned node, unsigned link)
78 {
79         device_t dev;
80         unsigned bus;
81
82         /* Find the device.
83          * There can only be one 8111 on a hypertransport chain/bus.
84          */
85         bus = node_link_to_bus(node, link);
86         dev = pci_locate_device(
87                 PCI_ID(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_ISA), 
88                 bus);
89
90         /* Reset */
91         set_bios_reset();
92         pci_write_config8(dev, 0x47, 1);
93 }