blob: 7fa9f12b0550dfbdf1a761358a615b357957226e [file] [log] [blame]
Timothy Pearson730a0432015-10-16 13:51:51 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/* Configure various power control registers, including processor
21 * boost support.
22 */
23
24#include <console/console.h>
25#include <device/device.h>
26#include <device/pci.h>
27#include <device/pci_ids.h>
28#include <device/pci_ops.h>
29#include <pc80/mc146818rtc.h>
30#include <lib.h>
31#include <cpu/amd/model_10xxx_rev.h>
32
33#include "amdfam10.h"
34
35static inline uint8_t is_fam15h(void)
36{
37 uint8_t fam15h = 0;
38 uint32_t family;
39
40 family = cpuid_eax(0x80000001);
41 family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
42
43 if (family >= 0x6f)
44 /* Family 15h or later */
45 fam15h = 1;
46
47 return fam15h;
48}
49
50static void nb_control_init(struct device *dev)
51{
Timothy Pearson83abd812015-06-08 19:35:06 -050052 uint8_t enable_c_states;
53 uint8_t enable_cc6;
Timothy Pearson730a0432015-10-16 13:51:51 -050054 uint32_t dword;
55
56 printk(BIOS_DEBUG, "NB: Function 4 Link Control.. ");
57
Timothy Pearson83abd812015-06-08 19:35:06 -050058 /* Configure L3 Power Control */
59 dword = pci_read_config32(dev, 0x1c4);
60 dword |= (0x1 << 8); /* L3PwrSavEn = 1 */
61 pci_write_config32(dev, 0x1c4, dword);
62
Timothy Pearson730a0432015-10-16 13:51:51 -050063 if (is_fam15h()) {
Timothy Pearson83abd812015-06-08 19:35:06 -050064 /* Configure L3 Control 2 */
65 dword = pci_read_config32(dev, 0x1cc);
66 dword &= ~(0x7 << 6); /* ImplRdProjDelayThresh = 0x2 */
67 dword |= (0x2 << 6);
68 pci_write_config32(dev, 0x1cc, dword);
69
70 /* Configure TDP Accumulator Divisor Control */
71 dword = pci_read_config32(dev, 0x104);
72 dword &= ~(0xfff << 2); /* TdpAccDivRate = 0xc8 */
73 dword |= (0xc8 << 2);
74 dword &= ~0x3; /* TdpAccDivVal = 0x1 */
75 dword |= 0x1;
76 pci_write_config32(dev, 0x104, dword);
77
78 /* Configure Sample and Residency Timers */
79 dword = pci_read_config32(dev, 0x110);
80 dword &= ~0xfff; /* CSampleTimer = 0x1 */
81 dword |= 0x1;
82 pci_write_config32(dev, 0x110, dword);
83
84 /* Configure APM TDP Control */
85 dword = pci_read_config32(dev, 0x16c);
86 dword |= (0x1 << 4); /* ApmTdpLimitIntEn = 1 */
87 pci_write_config32(dev, 0x16c, dword);
88
Timothy Pearson730a0432015-10-16 13:51:51 -050089 /* Enable APM */
90 dword = pci_read_config32(dev, 0x15c);
91 dword |= (0x1 << 7); /* ApmMasterEn = 1 */
92 pci_write_config32(dev, 0x15c, dword);
Timothy Pearson83abd812015-06-08 19:35:06 -050093
94 enable_c_states = 0;
95 enable_cc6 = 0;
96#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
97 uint8_t nvram;
98
99 if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS)
100 enable_c_states = !!nvram;
101
102 if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS)
103 enable_cc6 = !!nvram;
104#endif
105
106 if (enable_c_states) {
107 /* Configure C-state Control 1 */
108 dword = pci_read_config32(dev, 0x118);
109 dword |= (0x1 << 24); /* PwrGateEnCstAct1 = 1 */
110 dword &= ~(0x7 << 21); /* ClkDivisorCstAct1 = 0x0 */
111 dword &= ~(0x3 << 18); /* CacheFlushTmrSelCstAct1 = 0x1 */
112 dword |= (0x1 << 18);
113 dword |= (0x1 << 17); /* CacheFlushEnCstAct1 = 1 */
114 dword |= (0x1 << 16); /* CpuPrbEnCstAct1 = 1 */
115 dword &= ~(0x1 << 8); /* PwrGateEnCstAct0 = 0 */
116 dword &= ~(0x7 << 5); /* ClkDivisorCstAct0 = 0x0 */
117 dword &= ~(0x3 << 2); /* CacheFlushTmrSelCstAct0 = 0x2 */
118 dword |= (0x2 << 2);
119 dword |= (0x1 << 1); /* CacheFlushEnCstAct0 = 1 */
120 dword |= 0x1; /* CpuPrbEnCstAct0 = 1 */
121 pci_write_config32(dev, 0x118, dword);
122
123 /* Configure C-state Control 2 */
124 dword = pci_read_config32(dev, 0x11c);
125 dword &= ~(0x1 << 8); /* PwrGateEnCstAct2 = 0 */
126 dword &= ~(0x7 << 5); /* ClkDivisorCstAct2 = 0x0 */
127 dword &= ~(0x3 << 2); /* CacheFlushTmrSelCstAct0 = 0x0 */
128 dword &= ~(0x1 << 1); /* CacheFlushEnCstAct0 = 0 */
129 dword &= ~(0x1); /* CpuPrbEnCstAct0 = 0 */
130 pci_write_config32(dev, 0x11c, dword);
131
132 /* Configure C-state Policy Control 1 */
133 dword = pci_read_config32(dev, 0x128);
134 dword &= ~(0x7f << 5); /* CacheFlushTmr = 0x28 */
135 dword |= (0x28 << 5);
136 dword &= ~0x1; /* CoreCstateMode = !enable_cc6 */
137 dword |= ((enable_cc6)?0:1);
138 pci_write_config32(dev, 0x128, dword);
139 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500140 }
141
142 printk(BIOS_DEBUG, "done.\n");
143}
144
145
146static struct device_operations mcf4_ops = {
147 .read_resources = pci_dev_read_resources,
148 .set_resources = pci_dev_set_resources,
149 .enable_resources = pci_dev_enable_resources,
150 .init = nb_control_init,
151 .scan_bus = 0,
152 .ops_pci = 0,
153};
154
155static const struct pci_driver mcf4_driver_fam10 __pci_driver = {
156 .ops = &mcf4_ops,
157 .vendor = PCI_VENDOR_ID_AMD,
158 .device = 0x1204,
159};
160
161static const struct pci_driver mcf4_driver_fam15 __pci_driver = {
162 .ops = &mcf4_ops,
163 .vendor = PCI_VENDOR_ID_AMD,
164 .device = 0x1604,
Timothy Pearson83abd812015-06-08 19:35:06 -0500165};