blob: 4ddfea2b8ea51b1fb1437bc3e1e2c9e83328f498 [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"
Kyösti Mälkki29d9c562014-10-16 21:35:48 +030031#include "imc.h"
zbao246e84b2012-07-13 18:47:03 +080032#include "smbus.h"
Alexandru Gagniuc86777e32014-04-20 14:36:29 -050033#include "smi.h"
zbao246e84b2012-07-13 18:47:03 +080034
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050035/* Offsets from ACPI_MMIO_BASE
36 * This is defined by AGESA, but we don't include AGESA headers to avoid
Martin Roth3c3a50c2014-12-16 20:50:26 -070037 * polluting the namespace.
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050038 */
39#define PM_MMIO_BASE 0xfed80300
40
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050041void pm_write8(u8 reg, u8 value)
zbao246e84b2012-07-13 18:47:03 +080042{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080043 write8((void *)(PM_MMIO_BASE + reg), value);
zbao246e84b2012-07-13 18:47:03 +080044}
45
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050046u8 pm_read8(u8 reg)
zbao246e84b2012-07-13 18:47:03 +080047{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080048 return read8((void *)(PM_MMIO_BASE + reg));
zbao246e84b2012-07-13 18:47:03 +080049}
50
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050051void pm_write16(u8 reg, u16 value)
zbao246e84b2012-07-13 18:47:03 +080052{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080053 write16((void *)(PM_MMIO_BASE + reg), value);
zbao246e84b2012-07-13 18:47:03 +080054}
55
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050056u16 pm_read16(u16 reg)
zbao246e84b2012-07-13 18:47:03 +080057{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080058 return read16((void *)(PM_MMIO_BASE + reg));
zbao246e84b2012-07-13 18:47:03 +080059}
60
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -050061#define PM_REG_USB_ENABLE 0xef
62
63enum usb_enable {
64 USB_EN_DEVFN_12_0 = (1 << 0),
65 USB_EN_DEVFN_12_2 = (1 << 1),
66 USB_EN_DEVFN_13_0 = (1 << 2),
67 USB_EN_DEVFN_13_2 = (1 << 3),
68 USB_EN_DEVFN_16_0 = (1 << 4),
69 USB_EN_DEVFN_16_2 = (1 << 5),
70};
71
72static void hudson_disable_usb(u8 disable)
73{
74 u8 reg8;
75
76 /* Bit 7 handles routing, 6 is reserved. we don't mess with those */
77 disable &= 0x3f;
78
79 reg8 = pm_read8(PM_REG_USB_ENABLE);
80 reg8 &= ~disable;
81 pm_write8(PM_REG_USB_ENABLE, reg8);
82}
83
zbao246e84b2012-07-13 18:47:03 +080084void hudson_enable(device_t dev)
85{
Martin Rothf5726ea2013-01-18 12:55:40 -070086 printk(BIOS_DEBUG, "hudson_enable()\n");
Dave Frodinea909632013-05-31 08:15:57 -060087 switch (dev->path.pci.devfn) {
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -050088 case PCI_DEVFN(0x14, 7):
Dave Frodinea909632013-05-31 08:15:57 -060089 if (dev->enabled == 0) {
90 // read the VENDEV ID
91 device_t sd_dev = dev_find_slot( 0, PCI_DEVFN( 0x14, 7));
92 u32 sd_device_id = pci_read_config32( sd_dev, 0) >> 16;
93 /* turn off the SDHC controller in the PM reg */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050094 u8 reg8;
Dave Frodinea909632013-05-31 08:15:57 -060095 if (sd_device_id == PCI_DEVICE_ID_AMD_HUDSON_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050096 reg8 = pm_read8(0xe7);
97 reg8 &= ~(1 << 0);
98 pm_write8(0xe7, reg8);
Dave Frodinea909632013-05-31 08:15:57 -060099 }
100 else if (sd_device_id == PCI_DEVICE_ID_AMD_YANGTZE_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500101 reg8 = pm_read8(0xe8);
102 reg8 &= ~(1 << 0);
103 pm_write8(0xe8, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600104 }
105 /* remove device 0:14.7 from PCI space */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500106 reg8 = pm_read8(0xd3);
107 reg8 &= ~(1 << 6);
108 pm_write8(0xd3, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600109 }
110 break;
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -0500111
112 /* Make sure to disable other functions if function 0 is disabled */
113 case PCI_DEVFN(0x12, 0):
114 if (dev->enabled == 0)
115 hudson_disable_usb(USB_EN_DEVFN_12_0);
116 case PCI_DEVFN(0x12, 2): /* Fall through */
117 if (dev->enabled == 0)
118 hudson_disable_usb(USB_EN_DEVFN_12_2);
119 break;
120 case PCI_DEVFN(0x13, 0):
121 if (dev->enabled == 0)
122 hudson_disable_usb(USB_EN_DEVFN_13_0);
123 case PCI_DEVFN(0x13, 2): /* Fall through */
124 if (dev->enabled == 0)
125 hudson_disable_usb(USB_EN_DEVFN_13_2);
126 break;
127 case PCI_DEVFN(0x16, 0):
128 if (dev->enabled == 0)
129 hudson_disable_usb(USB_EN_DEVFN_16_0);
130 case PCI_DEVFN(0x16, 2): /* Fall through */
131 if (dev->enabled == 0)
132 hudson_disable_usb(USB_EN_DEVFN_16_2);
133 break;
Dave Frodinea909632013-05-31 08:15:57 -0600134 default:
135 break;
136 }
zbao246e84b2012-07-13 18:47:03 +0800137}
138
zbao246e84b2012-07-13 18:47:03 +0800139
Alexandru Gagniuc86777e32014-04-20 14:36:29 -0500140static void hudson_init_acpi_ports(void)
141{
142 /* We use some of these ports in SMM regardless of whether or not
143 * ACPI tables are generated. Enable these ports indiscriminately.
144 */
145
146 pm_write16(0x60, ACPI_PM_EVT_BLK);
147 pm_write16(0x62, ACPI_PM1_CNT_BLK);
148 pm_write16(0x64, ACPI_PM_TMR_BLK);
149 pm_write16(0x68, ACPI_GPE0_BLK);
150 /* CpuControl is in \_PR.CPU0, 6 bytes */
151 pm_write16(0x66, ACPI_CPU_CONTROL);
152
153 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
154 pm_write16(0x6a, ACPI_SMI_CTL_PORT);
155 hudson_enable_acpi_cmd_smi();
156 } else {
157 pm_write16(0x6a, 0);
158 }
159
160 /* AcpiDecodeEnable, When set, SB uses the contents of the PM registers
161 * at index 60-6B to decode ACPI I/O address. AcpiSmiEn & SmiCmdEn
162 */
163 pm_write8(0x74, 1<<0 | 1<<1 | 1<<4 | 1<<2);
164}
165
166static void hudson_init(void *chip_info)
167{
168 hudson_init_acpi_ports();
169}
170
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300171static void hudson_final(void *chip_info)
172{
WANG Siyuanb640fd32014-10-22 13:47:18 +0800173#if !CONFIG_ACPI_ENABLE_THERMAL_ZONE
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300174#if IS_ENABLED(CONFIG_HUDSON_IMC_FWM)
175 /* AMD AGESA does not enable thermal zone, so we enable it here. */
176 enable_imc_thermal_zone();
177#endif
WANG Siyuanb640fd32014-10-22 13:47:18 +0800178#endif
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300179}
180
zbao246e84b2012-07-13 18:47:03 +0800181struct chip_operations southbridge_amd_agesa_hudson_ops = {
182 CHIP_NAME("ATI HUDSON")
183 .enable_dev = hudson_enable,
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300184 .init = hudson_init,
185 .final = hudson_final
zbao246e84b2012-07-13 18:47:03 +0800186};