blob: 9fb81a63642a8994e76b0b45b0f6123adf34ae62 [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.
zbao246e84b2012-07-13 18:47:03 +080014 */
15
16#include <console/console.h>
17
18#include <arch/io.h>
19#include <arch/acpi.h>
20
21#include <device/device.h>
22#include <device/pci.h>
23#include <device/pci_ids.h>
24#include <device/pci_ops.h>
25#include <cbmem.h>
26#include "hudson.h"
Kyösti Mälkki29d9c562014-10-16 21:35:48 +030027#include "imc.h"
zbao246e84b2012-07-13 18:47:03 +080028#include "smbus.h"
Alexandru Gagniuc86777e32014-04-20 14:36:29 -050029#include "smi.h"
zbao246e84b2012-07-13 18:47:03 +080030
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050031/* Offsets from ACPI_MMIO_BASE
32 * This is defined by AGESA, but we don't include AGESA headers to avoid
Martin Roth3c3a50c2014-12-16 20:50:26 -070033 * polluting the namespace.
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050034 */
35#define PM_MMIO_BASE 0xfed80300
36
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050037void pm_write8(u8 reg, u8 value)
zbao246e84b2012-07-13 18:47:03 +080038{
Stefan Reinauer772029f2015-07-30 16:23:50 -070039 write8((void *)((uintptr_t)PM_MMIO_BASE + reg), value);
zbao246e84b2012-07-13 18:47:03 +080040}
41
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050042u8 pm_read8(u8 reg)
zbao246e84b2012-07-13 18:47:03 +080043{
Stefan Reinauer772029f2015-07-30 16:23:50 -070044 return read8((void *)((uintptr_t)PM_MMIO_BASE + reg));
zbao246e84b2012-07-13 18:47:03 +080045}
46
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050047void pm_write16(u8 reg, u16 value)
zbao246e84b2012-07-13 18:47:03 +080048{
Stefan Reinauer772029f2015-07-30 16:23:50 -070049 write16((void *)((uintptr_t)PM_MMIO_BASE + reg), value);
zbao246e84b2012-07-13 18:47:03 +080050}
51
Alexandru Gagniuc342ac642014-04-14 16:44:19 -050052u16 pm_read16(u16 reg)
zbao246e84b2012-07-13 18:47:03 +080053{
Stefan Reinauer772029f2015-07-30 16:23:50 -070054 return read16((void *)((uintptr_t)PM_MMIO_BASE + reg));
zbao246e84b2012-07-13 18:47:03 +080055}
56
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -050057#define PM_REG_USB_ENABLE 0xef
58
59enum usb_enable {
60 USB_EN_DEVFN_12_0 = (1 << 0),
61 USB_EN_DEVFN_12_2 = (1 << 1),
62 USB_EN_DEVFN_13_0 = (1 << 2),
63 USB_EN_DEVFN_13_2 = (1 << 3),
64 USB_EN_DEVFN_16_0 = (1 << 4),
65 USB_EN_DEVFN_16_2 = (1 << 5),
66};
67
68static void hudson_disable_usb(u8 disable)
69{
70 u8 reg8;
71
72 /* Bit 7 handles routing, 6 is reserved. we don't mess with those */
73 disable &= 0x3f;
74
75 reg8 = pm_read8(PM_REG_USB_ENABLE);
76 reg8 &= ~disable;
77 pm_write8(PM_REG_USB_ENABLE, reg8);
78}
79
Elyes HAOUASa93e7542018-05-19 14:30:47 +020080void hudson_enable(struct device *dev)
zbao246e84b2012-07-13 18:47:03 +080081{
Martin Rothf5726ea2013-01-18 12:55:40 -070082 printk(BIOS_DEBUG, "hudson_enable()\n");
Dave Frodinea909632013-05-31 08:15:57 -060083 switch (dev->path.pci.devfn) {
Tobias Diedrichae3adff2014-11-08 00:38:33 +010084 case PCI_DEVFN(0x14, 5):
85 if (dev->enabled == 0) {
Kyösti Mälkkib11d4e32018-05-20 10:39:10 +030086 u32 usb_device_id = pci_read_config32(dev, 0) >> 16;
Tobias Diedrichae3adff2014-11-08 00:38:33 +010087 u8 reg8;
Kyösti Mälkki9d9a5522016-11-19 22:14:59 +020088 if (usb_device_id == PCI_DEVICE_ID_AMD_SB900_USB_20_5) {
Tobias Diedrichae3adff2014-11-08 00:38:33 +010089 /* turn off and remove device 0:14.5 from PCI space */
90 reg8 = pm_read8(0xef);
91 reg8 &= ~(1 << 6);
92 pm_write8(0xef, reg8);
93 }
94 }
95 break;
96
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -050097 case PCI_DEVFN(0x14, 7):
Dave Frodinea909632013-05-31 08:15:57 -060098 if (dev->enabled == 0) {
Kyösti Mälkkib11d4e32018-05-20 10:39:10 +030099 u32 sd_device_id = pci_read_config32(dev, 0) >> 16;
Dave Frodinea909632013-05-31 08:15:57 -0600100 /* turn off the SDHC controller in the PM reg */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500101 u8 reg8;
Dave Frodinea909632013-05-31 08:15:57 -0600102 if (sd_device_id == PCI_DEVICE_ID_AMD_HUDSON_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500103 reg8 = pm_read8(0xe7);
104 reg8 &= ~(1 << 0);
105 pm_write8(0xe7, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600106 }
107 else if (sd_device_id == PCI_DEVICE_ID_AMD_YANGTZE_SD) {
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500108 reg8 = pm_read8(0xe8);
109 reg8 &= ~(1 << 0);
110 pm_write8(0xe8, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600111 }
112 /* remove device 0:14.7 from PCI space */
Alexandru Gagniuc342ac642014-04-14 16:44:19 -0500113 reg8 = pm_read8(0xd3);
114 reg8 &= ~(1 << 6);
115 pm_write8(0xd3, reg8);
Dave Frodinea909632013-05-31 08:15:57 -0600116 }
117 break;
Alexandru Gagniucd2e5f682014-04-16 16:33:03 -0500118
119 /* Make sure to disable other functions if function 0 is disabled */
120 case PCI_DEVFN(0x12, 0):
121 if (dev->enabled == 0)
122 hudson_disable_usb(USB_EN_DEVFN_12_0);
123 case PCI_DEVFN(0x12, 2): /* Fall through */
124 if (dev->enabled == 0)
125 hudson_disable_usb(USB_EN_DEVFN_12_2);
126 break;
127 case PCI_DEVFN(0x13, 0):
128 if (dev->enabled == 0)
129 hudson_disable_usb(USB_EN_DEVFN_13_0);
130 case PCI_DEVFN(0x13, 2): /* Fall through */
131 if (dev->enabled == 0)
132 hudson_disable_usb(USB_EN_DEVFN_13_2);
133 break;
134 case PCI_DEVFN(0x16, 0):
135 if (dev->enabled == 0)
136 hudson_disable_usb(USB_EN_DEVFN_16_0);
137 case PCI_DEVFN(0x16, 2): /* Fall through */
138 if (dev->enabled == 0)
139 hudson_disable_usb(USB_EN_DEVFN_16_2);
140 break;
Dave Frodinea909632013-05-31 08:15:57 -0600141 default:
142 break;
143 }
zbao246e84b2012-07-13 18:47:03 +0800144}
145
zbao246e84b2012-07-13 18:47:03 +0800146
Alexandru Gagniuc86777e32014-04-20 14:36:29 -0500147static void hudson_init_acpi_ports(void)
148{
149 /* We use some of these ports in SMM regardless of whether or not
150 * ACPI tables are generated. Enable these ports indiscriminately.
151 */
152
153 pm_write16(0x60, ACPI_PM_EVT_BLK);
154 pm_write16(0x62, ACPI_PM1_CNT_BLK);
155 pm_write16(0x64, ACPI_PM_TMR_BLK);
156 pm_write16(0x68, ACPI_GPE0_BLK);
Timothy Pearson033bb4b2015-02-10 22:21:39 -0600157 /* CpuControl is in \_PR.CP00, 6 bytes */
Alexandru Gagniuc86777e32014-04-20 14:36:29 -0500158 pm_write16(0x66, ACPI_CPU_CONTROL);
159
160 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
161 pm_write16(0x6a, ACPI_SMI_CTL_PORT);
162 hudson_enable_acpi_cmd_smi();
163 } else {
164 pm_write16(0x6a, 0);
165 }
166
167 /* AcpiDecodeEnable, When set, SB uses the contents of the PM registers
168 * at index 60-6B to decode ACPI I/O address. AcpiSmiEn & SmiCmdEn
169 */
170 pm_write8(0x74, 1<<0 | 1<<1 | 1<<4 | 1<<2);
171}
172
173static void hudson_init(void *chip_info)
174{
175 hudson_init_acpi_ports();
176}
177
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300178static void hudson_final(void *chip_info)
179{
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300180 /* AMD AGESA does not enable thermal zone, so we enable it here. */
Kyösti Mälkkieb064b32017-08-24 21:20:10 +0300181 if (IS_ENABLED(CONFIG_HUDSON_IMC_FWM) &&
182 !IS_ENABLED(CONFIG_ACPI_ENABLE_THERMAL_ZONE))
183 enable_imc_thermal_zone();
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300184}
185
zbao246e84b2012-07-13 18:47:03 +0800186struct chip_operations southbridge_amd_agesa_hudson_ops = {
187 CHIP_NAME("ATI HUDSON")
188 .enable_dev = hudson_enable,
Kyösti Mälkki29d9c562014-10-16 21:35:48 +0300189 .init = hudson_init,
190 .final = hudson_final
zbao246e84b2012-07-13 18:47:03 +0800191};