blob: 74650e7277797895b812b893741f6de06308443c [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.
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.
Zheng Baoeff2ffd2010-03-16 01:38:54 +000014 */
15
16#include <console/console.h>
17
18#include <arch/io.h>
19
20#include <device/device.h>
21#include <device/pci.h>
22#include <device/pci_ids.h>
23#include <device/pci_ops.h>
24#include "sb700.h"
25
26static device_t find_sm_dev(device_t dev, u32 devfn)
27{
28 device_t sm_dev;
29
30 sm_dev = dev_find_slot(dev->bus->secondary, devfn);
31 if (!sm_dev)
32 return sm_dev;
33
34 if ((sm_dev->vendor != PCI_VENDOR_ID_ATI) ||
35 ((sm_dev->device != PCI_DEVICE_ID_ATI_SB700_SM))) {
36 u32 id;
37 id = pci_read_config32(sm_dev, PCI_VENDOR_ID);
38 if ((id !=
39 (PCI_VENDOR_ID_ATI | (PCI_DEVICE_ID_ATI_SB700_SM << 16))))
40 {
41 sm_dev = 0;
42 }
43 }
44
45 return sm_dev;
46}
47
48void set_sm_enable_bits(device_t sm_dev, u32 reg_pos, u32 mask, u32 val)
49{
50 u32 reg_old, reg;
51 reg = reg_old = pci_read_config32(sm_dev, reg_pos);
52 reg &= ~mask;
53 reg |= val;
54 if (reg != reg_old) {
55 pci_write_config32(sm_dev, reg_pos, reg);
56 }
57}
58
59static void pmio_write_index(u16 port_base, u8 reg, u8 value)
60{
61 outb(reg, port_base);
62 outb(value, port_base + 1);
63}
64
65static u8 pmio_read_index(u16 port_base, u8 reg)
66{
67 outb(reg, port_base);
68 return inb(port_base + 1);
69}
70
71void pm_iowrite(u8 reg, u8 value)
72{
73 pmio_write_index(PM_INDEX, reg, value);
74}
75
76u8 pm_ioread(u8 reg)
77{
78 return pmio_read_index(PM_INDEX, reg);
79}
80
81void pm2_iowrite(u8 reg, u8 value)
82{
83 pmio_write_index(PM2_INDEX, reg, value);
84}
85
86u8 pm2_ioread(u8 reg)
87{
88 return pmio_read_index(PM2_INDEX, reg);
89}
90
91static void set_pmio_enable_bits(device_t sm_dev, u32 reg_pos,
92 u32 mask, u32 val)
93{
94 u8 reg_old, reg;
95 reg = reg_old = pm_ioread(reg_pos);
96 reg &= ~mask;
97 reg |= val;
98 if (reg != reg_old) {
99 pm_iowrite(reg_pos, reg);
100 }
101}
102
Zheng Baoc3422232011-03-28 03:33:10 +0000103void sb7xx_51xx_enable(device_t dev)
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000104{
105 device_t sm_dev = 0;
106 device_t bus_dev = 0;
107 int index = -1;
108 u32 deviceid;
109 u32 vendorid;
110
111 /* struct southbridge_ati_sb700_config *conf; */
112 /* conf = dev->chip_info; */
113 int i;
114
115 u32 devfn;
116
Zheng Baoc3422232011-03-28 03:33:10 +0000117 printk(BIOS_DEBUG, "sb7xx_51xx_enable()\n");
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000118
Zheng Baobfca8ef2010-06-19 06:55:17 +0000119 /*
120 * 0:11.0 SATA bit 8 of sm_dev 0xac : 1 - enable, default + 32 * 3
121 * 0:12.0 OHCI0-USB1 bit 0 of sm_dev 0x68
122 * 0:12.1 OHCI1-USB1 bit 1 of sm_dev 0x68
123 * 0:12.2 EHCI-USB1 bit 2 of sm_dev 0x68
124 * 0:13.0 OHCI0-USB2 bit 4 of sm_dev 0x68
125 * 0:13.1 OHCI1-USB2 bit 5 of sm_dev 0x68
126 * 0:13.2 EHCI-USB2 bit 6 of sm_dev 0x68
127 * 0:14.5 OHCI0-USB3 bit 7 of sm_dev 0x68
128 * 0:14.0 SMBUS 0
129 * 0:14.1 IDE 1
130 * 0:14.2 HDA bit 3 of pm_io 0x59 : 1 - enable, default + 32 * 4
131 * 0:14.3 LPC bit 20 of sm_dev 0x64 : 0 - disable, default + 32 * 1
132 * 0:14.4 PCI 4
133 */
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000134 if (dev->device == 0x0000) {
135 vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
136 deviceid = (vendorid >> 16) & 0xffff;
137 vendorid &= 0xffff;
138 } else {
139 vendorid = dev->vendor;
140 deviceid = dev->device;
141 }
Zheng Baobfca8ef2010-06-19 06:55:17 +0000142
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000143 bus_dev = dev->bus->dev;
144 if ((bus_dev->vendor == PCI_VENDOR_ID_ATI) &&
145 (bus_dev->device == PCI_DEVICE_ID_ATI_SB700_PCI)) {
146 devfn = (bus_dev->path.pci.devfn) & ~7;
147 sm_dev = find_sm_dev(bus_dev, devfn);
148 if (!sm_dev)
149 return;
150
151 /* something under 00:01.0 */
152 switch (dev->path.pci.devfn) {
153 case 5 << 3:
154 ;
155 }
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000156 return;
157 }
158
159 i = (dev->path.pci.devfn) & ~7;
Zheng Baoc3422232011-03-28 03:33:10 +0000160 i += (3 << 3);
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000161 for (devfn = (0x14 << 3); devfn <= i; devfn += (1 << 3)) {
162 sm_dev = find_sm_dev(dev, devfn);
163 if (sm_dev)
164 break;
165 }
166 if (!sm_dev)
167 return;
168
169 switch (dev->path.pci.devfn - (devfn - (0x14 << 3))) {
170 case (0x11 << 3) | 0:
171 index = 8;
172 set_sm_enable_bits(sm_dev, 0xac, 1 << index,
173 (dev->enabled ? 1 : 0) << index);
174 index += 32 * 3;
175 break;
176 case (0x12 << 3) | 0:
177 case (0x12 << 3) | 1:
178 case (0x12 << 3) | 2:
179 index = dev->path.pci.devfn & 3;
180 set_sm_enable_bits(sm_dev, 0x68, 1 << index,
181 (dev->enabled ? 1 : 0) << index);
182 index += 32 * 2;
183 break;
184 case (0x13 << 3) | 0:
185 case (0x13 << 3) | 1:
186 case (0x13 << 3) | 2:
187 index = (dev->path.pci.devfn & 3) + 4;
188 set_sm_enable_bits(sm_dev, 0x68, 1 << index,
189 (dev->enabled ? 1 : 0) << index);
190 index += 32 * 2;
191 break;
192 case (0x14 << 3) | 5:
193 index = 7;
194 set_sm_enable_bits(sm_dev, 0x68, 1 << index,
195 (dev->enabled ? 1 : 0) << index);
196 index += 32 * 2;
197 break;
198 case (0x14 << 3) | 0:
199 index = 0;
200 break;
201 case (0x14 << 3) | 1:
202 index = 1;
203 break;
204 case (0x14 << 3) | 2:
205 index = 3;
206 set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
207 (dev->enabled ? 1 : 0) << index);
208 index += 32 * 4;
209 break;
210 case (0x14 << 3) | 3:
211 index = 20;
212 set_sm_enable_bits(sm_dev, 0x64, 1 << index,
213 (dev->enabled ? 1 : 0) << index);
214 index += 32 * 1;
215 break;
216 case (0x14 << 3) | 4:
217 index = 4;
218 break;
219 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000220 printk(BIOS_DEBUG, "unknown dev: %s deviceid=%4x\n", dev_path(dev),
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000221 deviceid);
222 }
223}
224
Kyösti Mälkki399fcdd2012-02-23 18:42:55 +0200225#if CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100
226struct chip_operations southbridge_amd_sb700_ops = {
Zheng Baoc3422232011-03-28 03:33:10 +0000227 CHIP_NAME("ATI SP5100")
228 .enable_dev = sb7xx_51xx_enable,
229};
230#else
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000231struct chip_operations southbridge_amd_sb700_ops = {
232 CHIP_NAME("ATI SB700")
Zheng Baoc3422232011-03-28 03:33:10 +0000233 .enable_dev = sb7xx_51xx_enable,
Zheng Baoeff2ffd2010-03-16 01:38:54 +0000234};
Zheng Baoc3422232011-03-28 03:33:10 +0000235#endif