summaryrefslogtreecommitdiffstats
path: root/src/southbridge/broadcom/bcm5785/early_setup.c
blob: 9dee295c0d09e9a51a7ed35792cc1887776392c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2005 AMD
 * Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <reset.h>
#include "bcm5785.h"

static void bcm5785_enable_lpc(void)
{
        uint8_t byte;
        device_t dev;

        dev = pci_locate_device(PCI_ID(0x1166, 0x0234), 0);

        /* LPC Control 0 */
        byte = pci_read_config8(dev, 0x44);
        /* Serial 0 */
        byte |= (1<<6);
        pci_write_config8(dev, 0x44, byte);

        /* LPC Control 4 */
        byte = pci_read_config8(dev, 0x48);
        /* superio port 0x2e/4e enable */
        byte |=(1<<1)|(1<<0);
        pci_write_config8(dev, 0x48, byte);
}

static void bcm5785_enable_wdt_port_cf9(void)
{
        device_t dev;
        uint32_t dword;
        uint32_t dword_old;

        dev = pci_locate_device(PCI_ID(0x1166, 0x0205), 0);

        dword_old = pci_read_config32(dev, 0x4c);
        dword = dword_old | (1<<4); //enable Timer Func
        if(dword != dword_old ) {
                pci_write_config32(dev, 0x4c, dword);
        }

        dword_old = pci_read_config32(dev, 0x6c);
        dword = dword_old | (1<<9); //unhide Timer Func in pci space
        if(dword != dword_old ) {
                pci_write_config32(dev, 0x6c, dword);
        }

        dev = pci_locate_device(PCI_ID(0x1166, 0x0238), 0);

        /* enable cf9 */
        pci_write_config8(dev, 0x40, (1<<2));
}

unsigned get_sbdn(unsigned bus)
{
        device_t dev;

        /* Find the device.
         * There can only be one bcm5785 on a hypertransport chain/bus.
         */
        dev = pci_locate_device_on_bus(
                PCI_ID(0x1166, 0x0036),
                bus);

        return (dev>>15) & 0x1f;

}

#define SB_VFSMAF 0

void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn)
{
	//ACPI Decode Enable
	outb(0x0e, 0xcd6);
	outb((1<<3), 0xcd7);

	// set port to 0x2060
	outb(0x67, 0xcd6);
	outb(0x60, 0xcd7);
        outb(0x68, 0xcd6);
        outb(0x20, 0xcd7);

	outb(0x69, 0xcd6);
	outb(7, 0xcd7);

	outb(0x64, 0xcd6);
	outb(9, 0xcd7);
}

void ldtstop_sb(void)
{
	outb(1, 0x2060);
}


void hard_reset(void)
{
        bcm5785_enable_wdt_port_cf9();

        set_bios_reset();

        /* full reset */
        outb(0x0a, 0x0cf9);
        outb(0x0e, 0x0cf9);
}

void soft_reset(void)
{
        bcm5785_enable_wdt_port_cf9();

        set_bios_reset();
#if 1
        /* link reset */
//        outb(0x02, 0x0cf9);
        outb(0x06, 0x0cf9);
#endif
}

static void bcm5785_enable_msg(void)
{
        device_t dev;
        uint32_t dword;
        uint32_t dword_old;
        uint8_t byte;

        dev = pci_locate_device(PCI_ID(0x1166, 0x0205), 0);

        byte = pci_read_config8(dev, 0x42);
        byte = (1<<1); //enable a20
        pci_write_config8(dev, 0x42, byte);

        dword_old = pci_read_config32(dev, 0x6c);
        // bit 5: enable A20 Message
        // bit 4: enable interrupt messages
        // bit 3: enable reset init message
        // bit 2: enable keyboard init message
        // bit 1: enable upsteam messages
        // bit 0: enable shutdowm message to init generation
        dword = dword_old | (1<<5) | (1<<3) | (1<<2) | (1<<1) | (1<<0); // bit 1 and bit 4 must be set, otherwise interrupt msg will not be delivered to the processor
        if(dword != dword_old ) {
                pci_write_config32(dev, 0x6c, dword);
        }
}

static void bcm5785_early_setup(void)
{
        uint8_t byte;
        uint32_t dword;
        device_t dev;

//F0
        // enable device on bcm5785 at first
        dev = pci_locate_device(PCI_ID(0x1166, 0x0205), 0);
        dword = pci_read_config32(dev, 0x64);
        dword |=  (1<<15) | (1<<11) | (1<<3); // ioapci enable
        dword |= (1<<8); // USB enable
        dword |= /* (1<<27)|*/(1<<14); // IDE enable
        pci_write_config32(dev, 0x64, dword);

        byte = pci_read_config8(dev, 0x84);
        byte |= (1<<0); // SATA enable
        pci_write_config8(dev, 0x84, byte);

// WDT and cf9 for later in ramstage to call hard_reset
        bcm5785_enable_wdt_port_cf9();

        bcm5785_enable_msg();


// IDE related
	//F0
        byte = pci_read_config8(dev, 0x4e);
        byte |= (1<<4); //enable IDE ext regs
        pci_write_config8(dev, 0x4e, byte);

	//F1
        dev = pci_locate_device(PCI_ID(0x1166, 0x0214), 0);
        byte = pci_read_config8(dev, 0x48);
        byte &= ~1; // disable pri channel
        pci_write_config8(dev, 0x48, byte);
        pci_write_config8(dev, 0xb0, 0x01);
        pci_write_config8(dev, 0xb2, 0x02);
        byte = pci_read_config8(dev, 0x06);
        byte |= (1<<4); // so b0, b2 can not be changed from now
        pci_write_config8(dev, 0x06, byte);
        byte = pci_read_config8(dev, 0x49);
        byte |= 1; // enable second channel
        pci_write_config8(dev, 0x49, byte);

	//F2
        dev = pci_locate_device(PCI_ID(0x1166, 0x0234), 0);

        byte = pci_read_config8(dev, 0x40);
        byte |= (1<<3)|(1<<2); // LPC Retry, LPC to PCI DMA enable
        pci_write_config8(dev, 0x40, byte);

        pci_write_config32(dev, 0x60, 0x0000ffff); // LPC Memory hole start and end

// USB related
        pci_write_config8(dev, 0x90, 0x40);
        pci_write_config8(dev, 0x92, 0x06);
        pci_write_config8(dev, 0x9c, 0x7c); //PHY timinig register
        pci_write_config8(dev, 0xa4, 0x02); //mask reg - low/full speed func
        pci_write_config8(dev, 0xa5, 0x02); //mask reg - low/full speed func
        pci_write_config8(dev, 0xa6, 0x00); //mask reg - high speed func
        pci_write_config8(dev, 0xb4, 0x40);
}