aboutsummaryrefslogtreecommitdiff
path: root/src/southbridge/amd/cimx/sb800/bootblock.c
blob: b4f03dad7ecf0e5ddc6811cd07a9d92e72e24d58 (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
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2011 Advanced Micro Devices, Inc.
 *
 * 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 <arch/io.h>
#include <device/pci_ops.h>

static void enable_rom(void)
{
	u16 word;
	u32 dword;
	pci_devfn_t dev;

	dev = PCI_DEV(0, 0x14, 0x03);
	/* SB800 LPC Bridge 0:20:3:44h.
	 * BIT6: Port Enable for serial port 0x3f8-0x3ff
	 * BIT29: Port Enable for KBC port 0x60 and 0x64
	 * BIT30: Port Enable for ACPI Micro-Controller port 0x66 and 0x62
	 */
	dword = pci_io_read_config32(dev, 0x44);
	//dword |= (1<<6) | (1<<29) | (1<<30);
	/* Turn on all of LPC IO Port decode enable */
	dword = 0xffffffff;
	pci_io_write_config32(dev, 0x44, dword);

	/* SB800 LPC Bridge 0:20:3:48h.
	 * BIT0: Port Enable for SuperIO 0x2E-0x2F
	 * BIT1: Port Enable for SuperIO 0x4E-0x4F
	 * BIT4: Port Enable for LPC ROM Address Arrage2 (0x68-0x6C)
	 * BIT6: Port Enable for RTC IO 0x70-0x73
	 * BIT21: Port Enable for Port 0x80
	 */
	dword = pci_io_read_config32(dev, 0x48);
	dword |= (1 << 0) | (1 << 1) | (1 << 4) | (1 << 6) | (1 << 21);
	pci_io_write_config32(dev, 0x48, dword);

	/* Enable ROM access */
	word = pci_io_read_config16(dev, 0x6c);
	word = 0x10000 - (CONFIG_COREBOOT_ROMSIZE_KB >> 6);
	pci_io_write_config16(dev, 0x6c, word);
}

static void enable_prefetch(void)
{
	u32 dword;
	pci_devfn_t dev = PCI_DEV(0, 0x14, 0x03);

	/* Enable PrefetchEnSPIFromHost */
	dword = pci_io_read_config32(dev, 0xb8);
	pci_io_write_config32(dev, 0xb8, dword | (1 << 24));
}

static void enable_spi_fast_mode(void)
{
	u32 dword;
	pci_devfn_t dev = PCI_DEV(0, 0x14, 0x03);

	// set temp MMIO base
	volatile u32 *spi_base = (void *)0xa0000000;
	u32 save = pci_io_read_config32(dev, 0xa0);
	pci_io_write_config32(dev, 0xa0, (u32) spi_base | 2);

	// early enable of SPI 33 MHz fast mode read
	dword = spi_base[3];
	spi_base[3] = (dword & ~(3 << 14)) | (1 << 14);
	spi_base[0] = spi_base[0] | (1 << 18);	// fast read enable

	pci_io_write_config32(dev, 0xa0, save);
}

static void enable_acpimmio_decode_pm24(void)
{
	u8 reg8;

	outb(0x24, 0xCD6);
	reg8 = inb(0xCD7);
	reg8 |= 1;
	reg8 &= ~(1 << 1);
	outb(reg8, 0xCD7);
}

static void enable_clocks(void)
{
	u32 reg32;
	volatile u32 *acpi_mmio = (void *) (0xFED80000 + 0xE00 + 0x40);

	// Program SB800 MiscClkCntrl register to configure clock output on the
	// 14M_25M_48M_OSC ball usually used for the Super-I/O.
	// Almost all SIOs need 48 MHz, only the SMSC SCH311x wants 14 MHz,
	// which is the SB800's power up default.  We could switch back to 14
	// in the mainboard's romstage.c, but then the clock frequency would
	// change twice.
	reg32 = *acpi_mmio;
	reg32 &= ~((1 << 2) | (3 << 0)); // enable, 14 MHz (power up default)
#if !CONFIG(SUPERIO_WANTS_14MHZ_CLOCK)
	reg32 |= 2 << 0; // Device_CLK1_sel = 48 MHz
#endif
	*acpi_mmio = reg32;
}

static void bootblock_southbridge_init(void)
{
	/* Setup the ROM access for 2M */
	enable_rom();
	enable_prefetch();
	enable_spi_fast_mode();

	// Program AcpiMmioEn to enable MMIO access to MiscCntrl register
	enable_acpimmio_decode_pm24();
	enable_clocks();
}

#if !CONFIG(ROMCC_BOOTBLOCK)
#include <bootblock_common.h>

void bootblock_soc_early_init(void)
{
	bootblock_southbridge_init();
}
#endif