blob: 429749ef6b3cb10e03d96953cdbc59dfb7fd8361 [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
Patrick Georgib890a122015-03-26 15:17:45 +010017 * Foundation, Inc.
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{
Stefan Reinauer772029f2015-07-30 16:23:50 -070043 write8((void *)((uintptr_t)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{
Stefan Reinauer772029f2015-07-30 16:23:50 -070048 return read8((void *)((uintptr_t)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{
Stefan Reinauer772029f2015-07-30 16:23:50 -070053 write16((void *)((uintptr_t)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{
Stefan Reinauer772029f2015-07-30 16:23:50 -070058 return read16((void *)((uintptr_t)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) {
Tobias Diedrichae3adff2014-11-08 00:38:33 +010088 case PCI_DEVFN(0x14, 5):
89 if (dev->enabled == 0) {
90 // read the VENDEV ID
91 device_t usb_dev = dev_find_slot( 0, PCI_DEVFN( 0x14, 5));
92 u32 usb_device_id = pci_read_config32(usb_dev, 0) >> 16;
93 u8 reg8;
94 if (usb_device_id == PCI_DEVICE_ID_ATI_SB900_USB_20_5) {
95 /* turn off and remove device 0:14.5 from PCI space */
96 reg8 = pm_read8(0xef);
97 reg8 &= ~(1 << 6);
98 pm_write8(0xef, reg8);
99 }
100 }
101 break;
102
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -0500103 case PCI_DEVFN(0x14, 7):
Dave Frodinea909632013-05-31 08:15:57 -0600104 if (dev->enabled == 0) {
105 // read the VENDEV ID
106 device_t sd_dev = dev_find_slot( 0, PCI_DEVFN( 0x14, 7));
107 u32 sd_device_id = pci_read_config32( sd_dev, 0) >> 16;
108 /* turn off the SDHC controller in the PM reg */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500109 u8 reg8;
Dave Frodinea909632013-05-31 08:15:57 -0600110 if (sd_device_id == PCI_DEVICE_ID_AMD_HUDSON_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500111 reg8 = pm_read8(0xe7);
112 reg8 &= ~(1 << 0);
113 pm_write8(0xe7, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600114 }
115 else if (sd_device_id == PCI_DEVICE_ID_AMD_YANGTZE_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500116 reg8 = pm_read8(0xe8);
117 reg8 &= ~(1 << 0);
118 pm_write8(0xe8, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600119 }
120 /* remove device 0:14.7 from PCI space */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500121 reg8 = pm_read8(0xd3);
122 reg8 &= ~(1 << 6);
123 pm_write8(0xd3, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600124 }
125 break;
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -0500126
127 /* Make sure to disable other functions if function 0 is disabled */
128 case PCI_DEVFN(0x12, 0):
129 if (dev->enabled == 0)
130 hudson_disable_usb(USB_EN_DEVFN_12_0);
131 case PCI_DEVFN(0x12, 2): /* Fall through */
132 if (dev->enabled == 0)
133 hudson_disable_usb(USB_EN_DEVFN_12_2);
134 break;
135 case PCI_DEVFN(0x13, 0):
136 if (dev->enabled == 0)
137 hudson_disable_usb(USB_EN_DEVFN_13_0);
138 case PCI_DEVFN(0x13, 2): /* Fall through */
139 if (dev->enabled == 0)
140 hudson_disable_usb(USB_EN_DEVFN_13_2);
141 break;
142 case PCI_DEVFN(0x16, 0):
143 if (dev->enabled == 0)
144 hudson_disable_usb(USB_EN_DEVFN_16_0);
145 case PCI_DEVFN(0x16, 2): /* Fall through */
146 if (dev->enabled == 0)
147 hudson_disable_usb(USB_EN_DEVFN_16_2);
148 break;
Dave Frodinea909632013-05-31 08:15:57 -0600149 default:
150 break;
151 }
zbao246e84b2012-07-13 18:47:03 +0800152}
153
zbao246e84b2012-07-13 18:47:03 +0800154
Alexandru Gagniuc86777e32014-04-20 14:36:29 -0500155static void hudson_init_acpi_ports(void)
156{
157 /* We use some of these ports in SMM regardless of whether or not
158 * ACPI tables are generated. Enable these ports indiscriminately.
159 */
160
161 pm_write16(0x60, ACPI_PM_EVT_BLK);
162 pm_write16(0x62, ACPI_PM1_CNT_BLK);
163 pm_write16(0x64, ACPI_PM_TMR_BLK);
164 pm_write16(0x68, ACPI_GPE0_BLK);
Timothy Pearson033bb4b2015-02-10 22:21:39 -0600165 /* CpuControl is in \_PR.CP00, 6 bytes */
Alexandru Gagniuc86777e32014-04-20 14:36:29 -0500166 pm_write16(0x66, ACPI_CPU_CONTROL);
167
168 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
169 pm_write16(0x6a, ACPI_SMI_CTL_PORT);
170 hudson_enable_acpi_cmd_smi();
171 } else {
172 pm_write16(0x6a, 0);
173 }
174
175 /* AcpiDecodeEnable, When set, SB uses the contents of the PM registers
176 * at index 60-6B to decode ACPI I/O address. AcpiSmiEn & SmiCmdEn
177 */
178 pm_write8(0x74, 1<<0 | 1<<1 | 1<<4 | 1<<2);
179}
180
181static void hudson_init(void *chip_info)
182{
183 hudson_init_acpi_ports();
184}
185
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300186static void hudson_final(void *chip_info)
187{
WANG Siyuanb640fd32014-10-22 13:47:18 +0800188#if !CONFIG_ACPI_ENABLE_THERMAL_ZONE
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300189#if IS_ENABLED(CONFIG_HUDSON_IMC_FWM)
190 /* AMD AGESA does not enable thermal zone, so we enable it here. */
191 enable_imc_thermal_zone();
192#endif
WANG Siyuanb640fd32014-10-22 13:47:18 +0800193#endif
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300194}
195
zbao246e84b2012-07-13 18:47:03 +0800196struct chip_operations southbridge_amd_agesa_hudson_ops = {
197 CHIP_NAME("ATI HUDSON")
198 .enable_dev = hudson_enable,
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300199 .init = hudson_init,
200 .final = hudson_final
zbao246e84b2012-07-13 18:47:03 +0800201};