blob: af2b6c1bced5f3347e1edd23eadbdc17108a655d [file] [log] [blame]
Zheng Baoeff2ffd2010-03-16 01:38:54 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
Timothy Pearson056e4542016-04-06 13:18:52 -05005 * Copyright (C) 2015 - 2016 Raptor Engineering, LLC
Zheng Baoeff2ffd2010-03-16 01:38:54 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Zheng Baoeff2ffd2010-03-16 01:38:54 +000015 */
16
Uwe Hermannff492b12010-09-24 23:37:25 +000017#ifndef _SB700_EARLY_SETUP_C_
18#define _SB700_EARLY_SETUP_C_
Zheng Baoeff2ffd2010-03-16 01:38:54 +000019
efdesign9800c8c4a2011-07-20 12:37:58 -060020#include <stdint.h>
Timothy Pearson1b708652015-11-10 20:14:52 -060021#include <option.h>
efdesign9800c8c4a2011-07-20 12:37:58 -060022#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020023#include <device/pci_ops.h>
efdesign9800c8c4a2011-07-20 12:37:58 -060024#include <console/console.h>
25#include <cpu/x86/msr.h>
Kyösti Mälkki8a41f4b2019-02-08 18:14:34 +020026#include <device/pci.h>
efdesign9800c8c4a2011-07-20 12:37:58 -060027
Stefan Reinauer6a445e82010-04-09 11:34:59 +000028#include <reset.h>
Zheng Baoeff2ffd2010-03-16 01:38:54 +000029#include "sb700.h"
efdesign9800c8c4a2011-07-20 12:37:58 -060030#include "smbus.h"
Zheng Baoeff2ffd2010-03-16 01:38:54 +000031
Damien Zammit75a3d1f2016-11-28 00:29:10 +110032u32 get_sbdn(u32 bus);
33
Zheng Baoeff2ffd2010-03-16 01:38:54 +000034static void pmio_write(u8 reg, u8 value)
35{
36 outb(reg, PM_INDEX);
37 outb(value, PM_INDEX + 1);
38}
39
40static u8 pmio_read(u8 reg)
41{
42 outb(reg, PM_INDEX);
43 return inb(PM_INDEX + 1);
44}
45
Zheng Baoa5c949e2011-01-27 03:31:50 +000046static void sb700_acpi_init(void)
47{
Zheng Baoc3422232011-03-28 03:33:10 +000048 u16 word;
Rudolf Marekc4369532010-12-13 19:59:13 +000049 pmio_write(0x20, ACPI_PM_EVT_BLK & 0xFF);
50 pmio_write(0x21, ACPI_PM_EVT_BLK >> 8);
51 pmio_write(0x22, ACPI_PM1_CNT_BLK & 0xFF);
52 pmio_write(0x23, ACPI_PM1_CNT_BLK >> 8);
53 pmio_write(0x24, ACPI_PM_TMR_BLK & 0xFF);
54 pmio_write(0x25, ACPI_PM_TMR_BLK >> 8);
55 pmio_write(0x28, ACPI_GPE0_BLK & 0xFF);
56 pmio_write(0x29, ACPI_GPE0_BLK >> 8);
57
Timothy Pearson033bb4b2015-02-10 22:21:39 -060058 /* CpuControl is in \_PR.CP00, 6 bytes */
Rudolf Marekc4369532010-12-13 19:59:13 +000059 pmio_write(0x26, ACPI_CPU_CONTROL & 0xFF);
60 pmio_write(0x27, ACPI_CPU_CONTROL >> 8);
61
62 pmio_write(0x2A, 0); /* AcpiSmiCmdLo */
63 pmio_write(0x2B, 0); /* AcpiSmiCmdHi */
64
65 pmio_write(0x2C, ACPI_PMA_CNT_BLK & 0xFF);
66 pmio_write(0x2D, ACPI_PMA_CNT_BLK >> 8);
67
68 pmio_write(0x0E, 1<<3 | 0<<2); /* AcpiDecodeEnable, When set, SB uses
69 * the contents of the PM registers at
70 * index 20-2B to decode ACPI I/O address.
71 * AcpiSmiEn & SmiCmdEn*/
72 pmio_write(0x10, 1<<1 | 1<<3| 1<<5); /* RTC_En_En, TMR_En_En, GBL_EN_EN */
Zheng Baoc3422232011-03-28 03:33:10 +000073 word = inl(ACPI_PM1_CNT_BLK);
74 word |= 1;
75 outl(word, ACPI_PM1_CNT_BLK); /* set SCI_EN */
Rudolf Marekc4369532010-12-13 19:59:13 +000076}
77
Uwe Hermannff492b12010-09-24 23:37:25 +000078/* RPR 2.28: Get SB ASIC Revision. */
Zheng Baoeff2ffd2010-03-16 01:38:54 +000079static u8 set_sb700_revision(void)
80{
Antonello Dettori6cf44152016-09-03 10:45:33 +020081 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +000082 u8 rev_id, enable_14Mhz, byte;
83 u8 rev = 0;
84
85 /* if (rev != 0) return rev; */
86
87 dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
88
89 if (dev == PCI_DEV_INVALID) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +000090 die("SMBUS controller not found\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +000091 /* NOT REACHED */
92 }
93 rev_id = pci_read_config8(dev, 0x08);
94
95 if (rev_id == 0x39) {
96 enable_14Mhz = (pmio_read(0x53) >> 6) & 1;
97 if (enable_14Mhz == 0x0)
98 rev = 0x11; /* A11 */
99 else if (enable_14Mhz == 0x1) {
100 /* This happens, if does, only once. So later if we need to get
Zheng Bao2a5101a2010-10-10 15:18:53 +0000101 * the revision ID, we don't have to make such a big function.
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000102 * We just get reg 0x8 in smbus dev. 0x39 is A11, 0x3A is A12. */
103 rev = 0x12;
104 byte = pci_read_config8(dev, 0x40);
105 byte |= 1 << 0;
106 pci_write_config8(dev, 0x40, byte);
107
108 pci_write_config8(dev, 0x08, 0x3A); /* Change 0x39 to 0x3A. */
109
110 byte &= ~(1 << 0);
111 pci_write_config8(dev, 0x40, byte);
112 }
113 } else if (rev_id == 0x3A) { /* A12 will be 0x3A after BIOS is initialized */
114 rev = 0x12;
115 } else if (rev_id == 0x3C) {
116 rev = 0x14;
117 } else if (rev_id == 0x3D) {
118 rev = 0x15;
119 } else
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000120 die("It is not SB700 or SB710\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000121
122 return rev;
123}
124
125/***************************************
126* Legacy devices are mapped to LPC space.
127* Serial port 0
128* KBC Port
129* ACPI Micro-controller port
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000130* This function does not change port 0x80 decoding.
131* Console output through any port besides 0x3f8 is unsupported.
132* If you use FWH ROMs, you have to setup IDSEL.
133***************************************/
efdesign9800c8c4a2011-07-20 12:37:58 -0600134void sb7xx_51xx_lpc_init(void)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000135{
136 u8 reg8;
137 u32 reg32;
Antonello Dettori6cf44152016-09-03 10:45:33 +0200138 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000139
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000140 dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */
Zheng Baod4e77df2010-03-17 03:10:39 +0000141 /* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!!
142 * This bit has no meaning if debug strap is not enabled. So if the
143 * board keeps rebooting and the code fails to reach here, we could
144 * disable the debug strap first. */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000145 reg32 = pci_read_config32(dev, 0x4C);
146 reg32 |= 1 << 31;
147 pci_write_config32(dev, 0x4C, reg32);
148
149 /* Enable lpc controller */
150 reg32 = pci_read_config32(dev, 0x64);
151 reg32 |= 1 << 20;
152 pci_write_config32(dev, 0x64, reg32);
153
Martin Roth083504b2017-06-24 21:30:14 -0600154#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
Zheng Baoc3422232011-03-28 03:33:10 +0000155 post_code(0x66);
156 dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
157 reg8 = pci_read_config8(dev, 0xBB);
158 reg8 |= 1 << 2 | 1 << 3 | 1 << 6 | 1 << 7;
159 reg8 &= ~(1 << 1);
160 pci_write_config8(dev, 0xBB, reg8);
161#endif
162
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000163 dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
164 /* Decode port 0x3f8-0x3ff (Serial 0) */
Stefan Reinauer29ceae22010-04-20 11:03:41 +0000165 // XXX Serial port decode on LPC is hardcoded to 0x3f8
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000166 reg8 = pci_read_config8(dev, 0x44);
167 reg8 |= 1 << 6;
Martin Roth083504b2017-06-24 21:30:14 -0600168#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
Zheng Baoc3422232011-03-28 03:33:10 +0000169#if CONFIG_TTYS0_BASE == 0x2f8
170 reg8 |= 1 << 7;
171#endif
172#endif
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000173 pci_write_config8(dev, 0x44, reg8);
174
175 /* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/
176 reg8 = pci_read_config8(dev, 0x47);
177 reg8 |= (1 << 5) | (1 << 6);
178 pci_write_config8(dev, 0x47, reg8);
179
Scott Duplichand7acdfb2010-10-18 04:01:12 +0000180 /* Enable PrefetchEnSPIFromHost to speed up SPI flash read (does not affect LPC) */
181 reg8 = pci_read_config8(dev, 0xbb);
182 reg8 |= 1 << 0;
183 pci_write_config8(dev, 0xbb, reg8);
184
Uwe Hermann6e7efb72010-12-10 09:02:50 +0000185 /* Super I/O, RTC */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000186 reg8 = pci_read_config8(dev, 0x48);
187 /* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */
188 reg8 |= (1 << 1) | (1 << 0);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000189 /* Decode port 0x70-0x73 (RTC) */
Uwe Hermann6e7efb72010-12-10 09:02:50 +0000190 reg8 |= (1 << 6);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000191 pci_write_config8(dev, 0x48, reg8);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000192}
193
Zheng Baoc3422232011-03-28 03:33:10 +0000194void sb7xx_51xx_enable_wideio(u8 wio_index, u16 base)
195{
196 /* TODO: Now assume wio_index=0 */
Antonello Dettori6cf44152016-09-03 10:45:33 +0200197 pci_devfn_t dev;
Zheng Baoc3422232011-03-28 03:33:10 +0000198 u8 reg8;
199
200 dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
201 pci_write_config32(dev, 0x64, base);
202 reg8 = pci_read_config8(dev, 0x48);
203 reg8 |= 1 << 2;
204 pci_write_config8(dev, 0x48, reg8);
205}
206
207void sb7xx_51xx_disable_wideio(u8 wio_index)
208{
209 /* TODO: Now assume wio_index=0 */
Antonello Dettori6cf44152016-09-03 10:45:33 +0200210 pci_devfn_t dev;
Zheng Baoc3422232011-03-28 03:33:10 +0000211 u8 reg8;
212
213 dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
214 pci_write_config32(dev, 0x64, 0);
215 reg8 = pci_read_config8(dev, 0x48);
216 reg8 &= ~(1 << 2);
217 pci_write_config8(dev, 0x48, reg8);
218}
219
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000220/* what is its usage? */
Vladimir Serbinenko1765fd22014-11-09 16:33:25 +0100221u32 get_sbdn(u32 bus)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000222{
Antonello Dettori6cf44152016-09-03 10:45:33 +0200223 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000224
225 /* Find the device. */
226 dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus);
227 return (dev >> 15) & 0x1f;
228}
229
230static u8 dual_core(void)
231{
232 return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0;
233}
234
235/*
236 * RPR 2.4 C-state and VID/FID change for the K8 platform.
237 */
Vladimir Serbinenko1526b9f2014-11-09 16:36:03 +0100238void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000239{
240 u8 byte;
241 byte = pmio_read(0x9a);
242 byte &= ~0x34;
243 if (dual_core())
244 byte |= 0x34;
245 else
246 byte |= 0x04;
247 pmio_write(0x9a, byte);
248
249 byte = pmio_read(0x8f);
250 byte &= ~0x30;
251 byte |= 0x20;
252 pmio_write(0x8f, byte);
253
Martin Rothdcf253c2014-12-16 20:51:31 -0700254 pmio_write(0x8b, 0x01); /* TODO: if the HT Link is 200 MHz, it is 0x0A. It doesn't often happen. */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000255 pmio_write(0x8a, 0x90);
256
257 pmio_write(0x88, 0x10);
258
259 byte = pmio_read(0x7c);
260 byte |= 0x03;
261 pmio_write(0x7c, byte);
262
Uwe Hermannff492b12010-09-24 23:37:25 +0000263 /* Must be 0 for K8 platform. */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000264 byte = pmio_read(0x68);
265 byte &= ~0x01;
266 pmio_write(0x68, byte);
Uwe Hermannff492b12010-09-24 23:37:25 +0000267 /* Must be 0 for K8 platform. */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000268 byte = pmio_read(0x8d);
269 byte &= ~(1<<6);
270 pmio_write(0x8d, byte);
271
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000272 byte = pmio_read(0x42);
273 byte &= ~0x04;
274 pmio_write(0x42, byte);
275
276 pmio_write(0x89, 0x10);
Rudolf Marek199c6942011-02-26 13:34:01 +0000277
278 /* Toggle the LDT_STOP# during FID/VID Change, this bit is documented
279 only in SB600!
280 While here, enable C states too
281 */
282 pmio_write(0x67, 0x6);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000283}
284
Zheng Baoc3422232011-03-28 03:33:10 +0000285void sb7xx_51xx_pci_port80(void)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000286{
287 u8 byte;
Antonello Dettori6cf44152016-09-03 10:45:33 +0200288 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000289
290 /* P2P Bridge */
291 dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0);
292
293 /* Chip Control: Enable subtractive decoding */
294 byte = pci_read_config8(dev, 0x40);
295 byte |= 1 << 5;
296 pci_write_config8(dev, 0x40, byte);
297
298 /* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */
299 byte = pci_read_config8(dev, 0x4B);
300 byte |= 1 << 7;
301 pci_write_config8(dev, 0x4B, byte);
302
303 /* The same IO Base and IO Limit here is meaningful because we set the
304 * bridge to be subtractive. During early setup stage, we have to make
305 * sure that data can go through port 0x80.
306 */
307 /* IO Base: 0xf000 */
308 byte = pci_read_config8(dev, 0x1C);
309 byte |= 0xF << 4;
310 pci_write_config8(dev, 0x1C, byte);
311
312 /* IO Limit: 0xf000 */
313 byte = pci_read_config8(dev, 0x1D);
314 byte |= 0xF << 4;
315 pci_write_config8(dev, 0x1D, byte);
316
317 /* PCI Command: Enable IO response */
318 byte = pci_read_config8(dev, 0x04);
319 byte |= 1 << 0;
320 pci_write_config8(dev, 0x04, byte);
321
322 /* LPC controller */
323 dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0);
324
325 byte = pci_read_config8(dev, 0x4A);
326 byte &= ~(1 << 5); /* disable lpc port 80 */
327 pci_write_config8(dev, 0x4A, byte);
328}
329
Zheng Baoc3422232011-03-28 03:33:10 +0000330void sb7xx_51xx_lpc_port80(void)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000331{
332 u8 byte;
Antonello Dettori6cf44152016-09-03 10:45:33 +0200333 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000334 u32 reg32;
335
336 /* Enable LPC controller */
337 dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
338 reg32 = pci_read_config32(dev, 0x64);
339 reg32 |= 0x00100000; /* lpcEnable */
340 pci_write_config32(dev, 0x64, reg32);
341
342 /* Enable port 80 LPC decode in pci function 3 configuration space. */
343 dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0);
344 byte = pci_read_config8(dev, 0x4a);
345 byte |= 1 << 5; /* enable port 80 */
346 pci_write_config8(dev, 0x4a, byte);
347}
348
349/* sbDevicesPorInitTable */
350static void sb700_devices_por_init(void)
351{
Antonello Dettori6cf44152016-09-03 10:45:33 +0200352 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000353 u8 byte;
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500354 uint32_t dword;
355 uint8_t nvram;
356 uint8_t sata_ahci_mode;
357
358 sata_ahci_mode = 0;
359 if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
360 sata_ahci_mode = !!nvram;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000361
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000362 printk(BIOS_INFO, "sb700_devices_por_init()\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000363 /* SMBus Device, BDF:0-20-0 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000364 printk(BIOS_INFO, "sb700_devices_por_init(): SMBus Device, BDF:0-20-0\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000365 dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
366
367 if (dev == PCI_DEV_INVALID) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000368 die("SMBUS controller not found\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000369 /* NOT REACHED */
370 }
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000371 printk(BIOS_INFO, "SMBus controller enabled, sb revision is A%x\n",
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000372 set_sb700_revision());
373
374 /* sbPorAtStartOfTblCfg */
375 /* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0.
Martin Rothdcf253c2014-12-16 20:51:31 -0700376 * This is an I/O address. The I/O address must be on 16-byte boundary. */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000377 pci_write_config32(dev, 0xf0, AB_INDX);
378
379 /* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */
380 /* 4.3:Enables the SB700 to send transactions upstream over A-Link Express interface. */
381 axcfg_reg(0x04, 1 << 2, 1 << 2);
382 axindxc_reg(0x21, 0xff, 0);
383
384 /* 2.5:Enabling Non-Posted Memory Write for the K8 Platform */
385 axindxc_reg(0x10, 1 << 9, 1 << 9);
386 /* END of sbPorAtStartOfTblCfg */
387
388 /* sbDevicesPorInitTables */
389 /* set smbus iobase */
390 pci_write_config32(dev, 0x90, SMBUS_IO_BASE | 1);
391
392 /* enable smbus controller interface */
393 byte = pci_read_config8(dev, 0xd2);
394 byte |= (1 << 0);
395 pci_write_config8(dev, 0xd2, byte);
396
Timothy Pearsonee3ec8e2015-10-23 22:28:26 -0500397 /* set auxiliary smbus iobase and enable controller */
398 pci_write_config32(dev, 0x58, SMBUS_AUX_IO_BASE | 1);
399
400 if (inb(SMBUS_IO_BASE) == 0xff)
401 printk(BIOS_INFO, "%s: Primary SMBUS controller I/O not found\n", __func__);
402
Timothy Pearson796e77e2016-04-10 15:45:17 -0500403 if (inb(SMBUS_AUX_IO_BASE) == 0xff) {
Timothy Pearsonee3ec8e2015-10-23 22:28:26 -0500404 printk(BIOS_INFO, "%s: Secondary SMBUS controller I/O not found\n", __func__);
Timothy Pearson796e77e2016-04-10 15:45:17 -0500405 }
406 else {
407 if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)) {
408 /* Disable legacy sensor support / reset ASF Slave state machine per RPR 2.27 step 3 */
409 outb(0x40, SMBUS_AUX_IO_BASE + SMBSLVMISC);
410 }
411 }
Timothy Pearsonee3ec8e2015-10-23 22:28:26 -0500412
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000413 /* KB2RstEnable */
414 pci_write_config8(dev, 0x40, 0x44);
415
416 /* Enable ISA Address 0-960K decoding */
417 pci_write_config8(dev, 0x48, 0x0f);
418
419 /* Enable ISA Address 0xC0000-0xDFFFF decode */
420 pci_write_config8(dev, 0x49, 0xff);
421
422 /* Enable decode cycles to IO C50, C51, C52 GPM controls. */
423 byte = pci_read_config8(dev, 0x41);
424 byte &= 0x80;
425 byte |= 0x33;
426 pci_write_config8(dev, 0x41, byte);
427
428 /* Legacy DMA Prefetch Enhancement, CIM masked it. */
429 /* pci_write_config8(dev, 0x43, 0x1); */
430
Timothy Pearson8274acc2015-11-24 14:11:56 -0600431 /* Enable DMA verify bugfix */
432 byte = pci_read_config8(dev, 0x67);
433 byte |= 0x1 << 1;
434 pci_write_config8(dev, 0x67, byte);
435
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000436 /* Disabling Legacy USB Fast SMI# */
437 byte = pci_read_config8(dev, 0x62);
438 byte |= 0x24;
439 pci_write_config8(dev, 0x62, byte);
440
Dave Frodin37805972012-08-21 16:51:33 -0600441 /* Configure HPET Counter CLK period */
442 byte = pci_read_config8(dev, 0x43);
Timothy Pearson905507c2015-08-28 15:31:31 -0500443 byte &= 0xF7; /* Unhide HPET regs */
Dave Frodin37805972012-08-21 16:51:33 -0600444 pci_write_config8(dev, 0x43, byte);
Timothy Pearson905507c2015-08-28 15:31:31 -0500445 pci_write_config32(dev, 0x34, 0x0429b17e); /* Counter CLK period */
446 byte |= 0x08; /* Hide HPET regs */
Dave Frodin37805972012-08-21 16:51:33 -0600447 pci_write_config8(dev, 0x43, byte);
448
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000449 /* Features Enable */
450 pci_write_config32(dev, 0x64, 0x829E79BF); /* bit10: Enables the HPET interrupt. */
451
452 /* SerialIrq Control */
453 pci_write_config8(dev, 0x69, 0x90);
454
455 /* Test Mode, PCIB_SReset_En Mask is set. */
456 pci_write_config8(dev, 0x6c, 0x20);
457
458 /* IO Address Enable, CIM set 0x78 only and masked 0x79. */
459 /*pci_write_config8(dev, 0x79, 0x4F); */
460 pci_write_config8(dev, 0x78, 0xFF);
461
Timothy Pearson70f27362015-09-05 17:46:15 -0500462 if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
463 printk(BIOS_DEBUG, "%s: Disabling ISA DMA support\n", __func__);
464 /* Disable LPC ISA DMA Capability */
465 byte = pci_read_config8(dev, 0x78);
466 byte &= ~(1 << 0);
467 pci_write_config8(dev, 0x78, byte);
468 }
469
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000470 /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */
471 pci_write_config16(dev, 0x4, 0x0407);
472
473 /* clear any lingering errors, so the transaction will run */
474 outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
475
476 /* IDE Device, BDF:0-20-1 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000477 printk(BIOS_INFO, "sb700_devices_por_init(): IDE Device, BDF:0-20-1\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000478 dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0);
479 /* Disable prefetch */
480 byte = pci_read_config8(dev, 0x63);
481 byte |= 0x1;
482 pci_write_config8(dev, 0x63, byte);
483
484 /* LPC Device, BDF:0-20-3 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000485 printk(BIOS_INFO, "sb700_devices_por_init(): LPC Device, BDF:0-20-3\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000486 dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0);
Timothy Pearson85c39a42015-09-05 18:14:25 -0500487 if (!IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
488 /* DMA enable */
489 pci_write_config8(dev, 0x40, 0x04);
490 }
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000491
Zheng Baoc3422232011-03-28 03:33:10 +0000492 /* IO Port Decode Enable */
493 pci_write_config8(dev, 0x44, 0xFF);
494 pci_write_config8(dev, 0x45, 0xFF);
495 pci_write_config8(dev, 0x46, 0xC3);
496 pci_write_config8(dev, 0x47, 0xFF);
497
498 // TODO: This has already been done(?)
499 /* IO/Mem Port Decode Enable, I don't know why CIM disable some ports.
500 * Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f),
501 * Alternate Super I/O Configuration Port (4e/4f), Wide Generic IO Port (64/65). */
502 byte = pci_read_config8(dev, 0x48);
503 byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */
504 byte |= 1 << 6; /* enable for RTC I/O range */
505 pci_write_config8(dev, 0x48, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000506 pci_write_config8(dev, 0x49, 0xFF);
Zheng Baoc3422232011-03-28 03:33:10 +0000507 /* Enable 0x480-0x4bf, 0x4700-0x470B */
508 byte = pci_read_config8(dev, 0x4A);
Martin Rothdcf253c2014-12-16 20:51:31 -0700509 byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuration for port 0x80. */
Zheng Baoc3422232011-03-28 03:33:10 +0000510 pci_write_config8(dev, 0x4A, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000511
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000512 /* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */
513 pci_write_config8(dev, 0x7C, 0x05);
514
515 /* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM,
516 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000517 printk(BIOS_INFO, "sb700_devices_por_init(): P2P Bridge, BDF:0-20-4\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000518 dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0);
519
520 /* Arbiter enable. */
521 pci_write_config8(dev, 0x43, 0xff);
522
Martin Rothdcf253c2014-12-16 20:51:31 -0700523 /* Set PCDMA request into height priority list. */
Elyes HAOUAS18cd8a62016-10-03 20:41:04 +0200524 /* pci_write_config8(dev, 0x49, 0x1); */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000525
526 pci_write_config8(dev, 0x40, 0x26);
527
528 pci_write_config8(dev, 0x0d, 0x40);
529 pci_write_config8(dev, 0x1b, 0x40);
530 /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */
531 pci_write_config8(dev, 0x50, 0x01);
532
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500533 if (!sata_ahci_mode){
Martin Roth083504b2017-06-24 21:30:14 -0600534#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500535 /* SP5100 default SATA mode is RAID5 MODE */
Timothy Pearson1a383742015-10-25 18:58:24 -0500536 dev = pci_locate_device(PCI_ID(0x1002, 0x4392), 0);
Zheng Baoc3422232011-03-28 03:33:10 +0000537
Timothy Pearson1a383742015-10-25 18:58:24 -0500538 if (dev != PCI_DEV_INVALID) {
539 /* Set SATA Operation Mode, Set to IDE mode */
540 byte = pci_read_config8(dev, 0x40);
541 byte |= (1 << 0);
542 pci_write_config8(dev, 0x40, byte);
Zheng Baoc3422232011-03-28 03:33:10 +0000543
Timothy Pearson1a383742015-10-25 18:58:24 -0500544 dword = 0x01018f00;
545 pci_write_config32(dev, 0x8, dword);
Zheng Baoc3422232011-03-28 03:33:10 +0000546
Timothy Pearson1a383742015-10-25 18:58:24 -0500547 /* set SATA Device ID writable */
548 dword = pci_read_config32(dev, 0x40);
549 dword &= ~(1 << 24);
550 pci_write_config32(dev, 0x40, dword);
Zheng Baoc3422232011-03-28 03:33:10 +0000551
Timothy Pearson1a383742015-10-25 18:58:24 -0500552 /* set Device ID consistent with IDE emulation mode configuration */
553 pci_write_config32(dev, 0x0, 0x43901002);
Timothy Pearson1a383742015-10-25 18:58:24 -0500554 }
Zheng Baoc3422232011-03-28 03:33:10 +0000555#endif
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500556 }
Zheng Baoc3422232011-03-28 03:33:10 +0000557
Timothy Pearson2268e0d2016-04-05 23:10:48 -0500558 /* rpr v2.13 4.17 Reset CPU on Sync Flood */
559 abcfg_reg(0x10050, 1 << 2, 1 << 2);
560
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000561 /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500562 printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-17-0\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000563 dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0);
564
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500565 if (sata_ahci_mode) {
566 /* Switch to AHCI mode (AMD inbox) */
567 dword = pci_read_config32(dev, 0x40);
568 dword |= (0x1 << 24); /* Lock Flash Device ID = 1 */
569 pci_write_config32(dev, 0x40, dword);
570
571 /* Deactivate Sub-Class Code write protection */
572 byte = pci_read_config8(dev, 0x40);
573 byte |= (1 << 0);
574 pci_write_config8(dev, 0x40, byte);
575
576 dword = pci_read_config32(dev, 0x08);
577 dword &= ~(0xff << 16); /* Sub-Class Code = 0x6 */
578 dword |= (0x6 << 16);
579 dword &= ~(0xff << 8); /* Operating Mode Selection = 0x1 */
580 dword |= (0x1 << 8);
581 pci_write_config32(dev, 0x08, dword);
582 }
583
584 /* PHY Global Control */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000585 pci_write_config16(dev, 0x86, 0x2C00);
586}
587
588/* sbPmioPorInitTable, Pre-initializing PMIO register space
589* The power management (PM) block is resident in the PCI/LPC/ISA bridge.
590* The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7.
591* The index address is first programmed into IO reg 0xcd6.
592* Read or write values are accessed through IO reg 0xcd7.
593*/
594static void sb700_pmio_por_init(void)
595{
596 u8 byte;
Timothy Pearson83abd812015-06-08 19:35:06 -0500597 uint8_t enable_c_states;
598
599 enable_c_states = 0;
600#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
601 if (get_option(&byte, "cpu_c_states") == CB_SUCCESS)
602 enable_c_states = !!byte;
603#endif
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000604
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000605 printk(BIOS_INFO, "sb700_pmio_por_init()\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000606 /* K8KbRstEn, KB_RST# control for K8 system. */
607 byte = pmio_read(0x66);
608 byte |= 0x20;
609 pmio_write(0x66, byte);
610
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500611 if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)) {
612 /* RPR 2.11 Sx State Settings */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000613 byte = pmio_read(0x65);
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500614 byte &= ~(1 << 7); /* SpecialFunc = 0 */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000615 pmio_write(0x65, byte);
616
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500617 byte = pmio_read(0x68);
618 byte |= 1 << 2; /* MaskApicEn = 1 */
619 pmio_write(0x68, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000620 } else {
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500621 /* RPR2.31 PM_TURN_OFF_MSG during ASF Shutdown. */
622 if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) {
623 byte = pmio_read(0x65);
624 byte &= ~(1 << 7);
625 pmio_write(0x65, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000626
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500627 byte = pmio_read(0x75);
628 byte &= 0xc0;
629 byte |= 0x05;
630 pmio_write(0x75, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000631
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500632 byte = pmio_read(0x52);
633 byte &= 0xc0;
634 byte |= 0x08;
635 pmio_write(0x52, byte);
636 } else {
637 byte = pmio_read(0xD7);
638 byte |= 1 << 0;
639 pmio_write(0xD7, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000640
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500641 byte = pmio_read(0x65);
642 byte |= 1 << 7;
643 pmio_write(0x65, byte);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000644
Timothy Pearsonc13866f2016-04-10 16:02:42 -0500645 byte = pmio_read(0x75);
646 byte &= 0xc0;
647 byte |= 0x01;
648 pmio_write(0x75, byte);
649
650 byte = pmio_read(0x52);
651 byte &= 0xc0;
652 byte |= 0x02;
653 pmio_write(0x52, byte);
654 }
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000655 }
656
657 /* Watch Dog Timer Control
658 * Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure.
659 * But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM.
660 */
661 pmio_write(0x6c, 0xf0);
662 pmio_write(0x6d, 0x00);
663 pmio_write(0x6e, 0xc0);
664 pmio_write(0x6f, 0xfe);
665
666 /* rpr2.15: Enabling Spread Spectrum */
667 byte = pmio_read(0x42);
668 byte |= 1 << 7;
669 pmio_write(0x42, byte);
670 /* TODO: Check if it is necessary. IDE reset */
671 byte = pmio_read(0xB2);
672 byte |= 1 << 0;
673 pmio_write(0xB2, byte);
Timothy Pearson85c39a42015-09-05 18:14:25 -0500674
Timothy Pearson83abd812015-06-08 19:35:06 -0500675 /* Set up IOAPIC and BM_STS monitoring */
676 byte = pmio_read(0x61);
677 if (enable_c_states)
678 byte |= 0x4;
679 else
680 byte &= ~0x04;
681 pmio_write(0x61, byte);
682
Martin Rotheabce722015-10-27 14:10:22 -0600683 /* NOTE: Enabling automatic C1e state switch caused failures when initializing processors */
Timothy Pearson85c39a42015-09-05 18:14:25 -0500684
685 /* Enable precision HPET clock and automatic C state switch */
686 byte = pmio_read(0xbb);
687 byte |= 0xc0;
688 pmio_write(0xbb, byte);
Timothy Pearson905507c2015-08-28 15:31:31 -0500689
Martin Roth083504b2017-06-24 21:30:14 -0600690#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
Timothy Pearsond1b6ff82016-04-10 15:52:47 -0500691 /* RPR 2.26 Alter CPU reset timing */
692 byte = pmio_read(0xb2);
693 byte |= 0x1 << 2; /* Enable CPU reset timing option */
694 pmio_write(0xb2, byte);
695
Timothy Pearson905507c2015-08-28 15:31:31 -0500696 /* Work around system clock drift issues */
697 byte = pmio_read(0xd4);
698 byte |= 0x1 << 6; /* Enable alternate 14MHz clock source */
699 byte |= 0x1 << 7; /* Disable 25MHz oscillator buffer */
700 pmio_write(0xd4, byte);
701#endif
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000702}
703
704/*
705* Add any south bridge setting.
706*/
707static void sb700_pci_cfg(void)
708{
Antonello Dettori6cf44152016-09-03 10:45:33 +0200709 pci_devfn_t dev;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000710 u8 byte;
Timothy Pearson22dfccf2015-06-09 19:12:35 -0500711 uint8_t acpi_s1_supported = 1;
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000712
713 /* SMBus Device, BDF:0-20-0 */
714 dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
Timothy Pearson0a105cd2015-12-08 12:09:06 -0600715
716 /* Enable watchdog timer decode */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000717 byte = pci_read_config8(dev, 0x41);
718 byte |= (1 << 3);
719 pci_write_config8(dev, 0x41, byte);
720
721 /* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles)
722 * generated PCIRST#. */
723 byte = pmio_read(0x65);
724 byte |= (1 << 4);
725 pmio_write(0x65, byte);
726
727 /* IDE Device, BDF:0-20-1 */
728 dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0);
729 /* Enable IDE Explicit prefetch, 0x63[0] clear */
730 byte = pci_read_config8(dev, 0x63);
731 byte &= 0xfe;
732 pci_write_config8(dev, 0x63, byte);
733
734 /* LPC Device, BDF:0-20-3 */
735 /* The code below is ported from old chipset. It is not
Zheng Bao2a5101a2010-10-10 15:18:53 +0000736 * mentioned in RPR. But I keep them. The registers and the
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000737 * comments are compatible. */
738 dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0);
Timothy Pearson85c39a42015-09-05 18:14:25 -0500739 if (!IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
740 /* Enabling LPC DMA function. */
741 byte = pci_read_config8(dev, 0x40);
742 byte |= (1 << 2);
743 pci_write_config8(dev, 0x40, byte);
744 }
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000745 /* Disabling LPC TimeOut. 0x48[7] clear. */
746 byte = pci_read_config8(dev, 0x48);
747 byte &= 0x7f;
748 pci_write_config8(dev, 0x48, byte);
749 /* Disabling LPC MSI Capability, 0x78[1] clear. */
750 byte = pci_read_config8(dev, 0x78);
751 byte &= 0xfd;
752 pci_write_config8(dev, 0x78, byte);
753
754 /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */
755 dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0);
Timothy Pearson5d7dc552015-06-09 18:09:50 -0500756 if (dev == PCI_DEV_INVALID)
757 dev = pci_locate_device(PCI_ID(0x1002, 0x4391), 0);
758 if (dev == PCI_DEV_INVALID)
759 dev = pci_locate_device(PCI_ID(0x1002, 0x4394), 0);
760
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000761 /* rpr7.12 SATA MSI and D3 Power State Capability. */
762 byte = pci_read_config8(dev, 0x40);
763 byte |= 1 << 0;
764 pci_write_config8(dev, 0x40, byte);
Timothy Pearson22dfccf2015-06-09 19:12:35 -0500765 if (acpi_s1_supported)
766 pci_write_config8(dev, 0x34, 0x70); /* Hide D3 power state and MSI capabilities */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000767 else
Timothy Pearson22dfccf2015-06-09 19:12:35 -0500768 pci_write_config8(dev, 0x61, 0x70); /* Hide MSI capability */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000769 byte &= ~(1 << 0);
770 pci_write_config8(dev, 0x40, byte);
771}
772
773/*
774*/
775static void sb700_por_init(void)
776{
777 /* sbDevicesPorInitTable + sbK8PorInitTable */
778 sb700_devices_por_init();
779
780 /* sbPmioPorInitTable + sbK8PmioPorInitTable */
781 sb700_pmio_por_init();
782}
783
Timothy Pearson056e4542016-04-06 13:18:52 -0500784uint16_t sb7xx_51xx_decode_last_reset(void) {
785 uint16_t reset_status = 0;
786 reset_status |= pmio_read(0x44);
787 reset_status |= (pmio_read(0x45) << 8);
788 printk(BIOS_INFO, "sb700 reset flags: %04x\n", reset_status);
789 if (reset_status & (0x1 << 10))
790 printk(BIOS_WARNING, "WARNING: Last reset was caused by fatal error / sync flood!\n");
791
792 return reset_status;
793}
794
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000795/*
796* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration.
797*/
efdesign9800c8c4a2011-07-20 12:37:58 -0600798void sb7xx_51xx_before_pci_init(void)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000799{
800 sb700_pci_cfg();
801}
802
803/*
804* This function should be called after enable_sb700_smbus().
805*/
efdesign9800c8c4a2011-07-20 12:37:58 -0600806void sb7xx_51xx_early_setup(void)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000807{
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000808 printk(BIOS_INFO, "sb700_early_setup()\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000809 sb700_por_init();
Rudolf Marekc4369532010-12-13 19:59:13 +0000810 sb700_acpi_init();
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000811}
812
Zheng Baoa5c949e2011-01-27 03:31:50 +0000813int s3_save_nvram_early(u32 dword, int size, int nvram_pos)
814{
Rudolf Marekc4369532010-12-13 19:59:13 +0000815 int i;
816 printk(BIOS_DEBUG, "Writing %x of size %d to nvram pos: %d\n", dword, size, nvram_pos);
817
Elyes HAOUASc021ffe2016-09-18 19:18:56 +0200818 for (i = 0; i < size; i++) {
Rudolf Marekc4369532010-12-13 19:59:13 +0000819 outb(nvram_pos, BIOSRAM_INDEX);
Elyes HAOUASa342f392018-10-17 10:56:26 +0200820 outb((dword >> (8 * i)) & 0xff, BIOSRAM_DATA);
Rudolf Marekc4369532010-12-13 19:59:13 +0000821 nvram_pos++;
822 }
823
824 return nvram_pos;
825}
826
Zheng Baoa5c949e2011-01-27 03:31:50 +0000827int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos)
828{
Rudolf Marekc4369532010-12-13 19:59:13 +0000829 u32 data = *old_dword;
830 int i;
Elyes HAOUASc021ffe2016-09-18 19:18:56 +0200831 for (i = 0; i < size; i++) {
Rudolf Marekc4369532010-12-13 19:59:13 +0000832 outb(nvram_pos, BIOSRAM_INDEX);
833 data &= ~(0xff << (i * 8));
834 data |= inb(BIOSRAM_DATA) << (i *8);
835 nvram_pos++;
836 }
837 *old_dword = data;
838 printk(BIOS_DEBUG, "Loading %x of size %d to nvram pos:%d\n", *old_dword, size,
839 nvram_pos-size);
840 return nvram_pos;
841}
842
Timothy Pearson85c39a42015-09-05 18:14:25 -0500843void set_lpc_sticky_ctl(bool enable)
844{
845 uint8_t byte;
846
847 byte = pmio_read(0xbb);
848 if (enable)
849 byte |= 0x20;
850 else
851 byte &= ~0x20;
852 pmio_write(0xbb, byte);
853}
854
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000855#endif