blob: 39dab23d0d2e6b6e5c61ad9d5964160d0399a6d6 [file] [log] [blame]
zbao246e84b2012-07-13 18:47:03 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
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
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
zbao246e84b2012-07-13 18:47:03 +080018 */
19
20#include <console/console.h>
21
22#include <arch/io.h>
23#include <arch/acpi.h>
24
25#include <device/device.h>
26#include <device/pci.h>
27#include <device/pci_ids.h>
28#include <device/pci_ops.h>
29#include <cbmem.h>
30#include "hudson.h"
31#include "smbus.h"
32
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050033/* Offsets from ACPI_MMIO_BASE
34 * This is defined by AGESA, but we don't include AGESA headers to avoid
35 * polluting the namesace.
36 */
37#define PM_MMIO_BASE 0xfed80300
38
39
Stefan Reinauer8ada1522012-11-16 13:34:48 -080040#if CONFIG_HAVE_ACPI_RESUME
zbao246e84b2012-07-13 18:47:03 +080041int acpi_get_sleep_type(void)
42{
Alexandru Gagniuccf1f9b62014-04-20 13:24:42 -050043 u16 tmp = inw(ACPI_PM1_CNT_BLK);
zbao246e84b2012-07-13 18:47:03 +080044 tmp = ((tmp & (7 << 10)) >> 10);
45 /* printk(BIOS_DEBUG, "SLP_TYP type was %x\n", tmp); */
46 return (int)tmp;
47}
48#endif
49
Kyösti Mälkkibc90e152013-09-04 13:26:11 +030050void backup_top_of_ram(uint64_t ramtop)
zbao246e84b2012-07-13 18:47:03 +080051{
Kyösti Mälkkibc90e152013-09-04 13:26:11 +030052 u32 dword = (u32) ramtop;
zbao246e84b2012-07-13 18:47:03 +080053 int nvram_pos = 0xf8, i; /* temp */
54 /* printk(BIOS_DEBUG, "dword=%x\n", dword); */
55 for (i = 0; i<4; i++) {
56 /* printk(BIOS_DEBUG, "nvram_pos=%x, dword>>(8*i)=%x\n", nvram_pos, (dword >>(8 * i)) & 0xff); */
57 outb(nvram_pos, BIOSRAM_INDEX);
58 outb((dword >>(8 * i)) & 0xff , BIOSRAM_DATA);
59 nvram_pos++;
60 }
61}
62
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050063void pm_write8(u8 reg, u8 value)
zbao246e84b2012-07-13 18:47:03 +080064{
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050065 write8(PM_MMIO_BASE + reg, value);
zbao246e84b2012-07-13 18:47:03 +080066}
67
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050068u8 pm_read8(u8 reg)
zbao246e84b2012-07-13 18:47:03 +080069{
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050070 return read8(PM_MMIO_BASE + reg);
zbao246e84b2012-07-13 18:47:03 +080071}
72
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050073void pm_write16(u8 reg, u16 value)
zbao246e84b2012-07-13 18:47:03 +080074{
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050075 write16(PM_MMIO_BASE + reg, value);
zbao246e84b2012-07-13 18:47:03 +080076}
77
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050078u16 pm_read16(u16 reg)
zbao246e84b2012-07-13 18:47:03 +080079{
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050080 return read16(PM_MMIO_BASE + reg);
zbao246e84b2012-07-13 18:47:03 +080081}
82
zbao246e84b2012-07-13 18:47:03 +080083void hudson_enable(device_t dev)
84{
Martin Rothf5726ea2013-01-18 12:55:40 -070085 printk(BIOS_DEBUG, "hudson_enable()\n");
Dave Frodinea909632013-05-31 08:15:57 -060086 switch (dev->path.pci.devfn) {
87 case (0x14 << 3) | 7: /* 0:14.7 SD */
88 if (dev->enabled == 0) {
89 // read the VENDEV ID
90 device_t sd_dev = dev_find_slot( 0, PCI_DEVFN( 0x14, 7));
91 u32 sd_device_id = pci_read_config32( sd_dev, 0) >> 16;
92 /* turn off the SDHC controller in the PM reg */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050093 u8 reg8;
Dave Frodinea909632013-05-31 08:15:57 -060094 if (sd_device_id == PCI_DEVICE_ID_AMD_HUDSON_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050095 reg8 = pm_read8(0xe7);
96 reg8 &= ~(1 << 0);
97 pm_write8(0xe7, reg8);
Dave Frodinea909632013-05-31 08:15:57 -060098 }
99 else if (sd_device_id == PCI_DEVICE_ID_AMD_YANGTZE_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500100 reg8 = pm_read8(0xe8);
101 reg8 &= ~(1 << 0);
102 pm_write8(0xe8, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600103 }
104 /* remove device 0:14.7 from PCI space */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500105 reg8 = pm_read8(0xd3);
106 reg8 &= ~(1 << 6);
107 pm_write8(0xd3, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600108 }
109 break;
110 default:
111 break;
112 }
zbao246e84b2012-07-13 18:47:03 +0800113}
114
Kyösti Mälkkibc90e152013-09-04 13:26:11 +0300115#if CONFIG_HAVE_ACPI_RESUME
116unsigned long get_top_of_ram(void)
zbao246e84b2012-07-13 18:47:03 +0800117{
118 uint32_t xdata = 0;
119 int xnvram_pos = 0xf8, xi;
Kyösti Mälkkibc90e152013-09-04 13:26:11 +0300120 if (acpi_get_sleep_type() != 3)
121 return 0;
zbao246e84b2012-07-13 18:47:03 +0800122 for (xi = 0; xi<4; xi++) {
123 outb(xnvram_pos, BIOSRAM_INDEX);
124 xdata &= ~(0xff << (xi * 8));
125 xdata |= inb(BIOSRAM_DATA) << (xi *8);
126 xnvram_pos++;
127 }
Kyösti Mälkkibc90e152013-09-04 13:26:11 +0300128 return (unsigned long) xdata;
zbao246e84b2012-07-13 18:47:03 +0800129}
Kyösti Mälkkibc90e152013-09-04 13:26:11 +0300130#endif
zbao246e84b2012-07-13 18:47:03 +0800131
132struct chip_operations southbridge_amd_agesa_hudson_ops = {
133 CHIP_NAME("ATI HUDSON")
134 .enable_dev = hudson_enable,
135};