summaryrefslogtreecommitdiff
path: root/src/southbridge/broadcom/bcm5785/early_setup.c
blob: 72354440c9f09d09a255ded8df9336d2fcbfdffe (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
/*
 * 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.
 */

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

static void bcm5785_enable_lpc(void)
{
	uint8_t byte;
	pci_devfn_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)
{
	pci_devfn_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)
{
	pci_devfn_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 do_hard_reset(void)
{
	bcm5785_enable_wdt_port_cf9();

	set_bios_reset();

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

void do_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)
{
	pci_devfn_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;
	pci_devfn_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);
}