blob: 27bd3319fe916769a343eaea2d134f4ff8a9f98c [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
4 * Copyright (C) 2007 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.
Marc Jones8ae8c882007-12-19 01:32:08 +000014 */
15
16/*
Stefan Reinauer38f147e2010-02-08 12:20:50 +000017 * Generic FAM10 debug code, used by mainboard specific romstage.c
Marc Jones8ae8c882007-12-19 01:32:08 +000018 */
19
stepan8301d832010-12-08 07:07:33 +000020#include "pci.c"
Myles Watson075fbe82010-04-15 05:19:29 +000021#include <delay.h>
Marc Jones8ae8c882007-12-19 01:32:08 +000022
Stefan Reinauer8b547b12010-03-30 09:56:35 +000023static inline void print_debug_addr(const char *str, void *val)
Marc Jones8ae8c882007-12-19 01:32:08 +000024{
Patrick Georgie82618d2010-10-01 14:50:12 +000025#if CONFIG_DEBUG_CAR
Myles Watson08e0fb82010-03-22 16:33:25 +000026 printk(BIOS_DEBUG, "------Address debug: %s%p------\n", str, val);
Marc Jones8ae8c882007-12-19 01:32:08 +000027#endif
28}
29
30static void print_debug_pci_dev(u32 dev)
31{
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000032 printk(BIOS_DEBUG, "PCI: %02x:%02x.%02x", (dev>>20) & 0xff, (dev>>15) & 0x1f, (dev>>12) & 0x7);
Marc Jones8ae8c882007-12-19 01:32:08 +000033}
34
Stefan Reinauer8b547b12010-03-30 09:56:35 +000035static inline void print_pci_devices(void)
Marc Jones8ae8c882007-12-19 01:32:08 +000036{
37 device_t dev;
38 for(dev = PCI_DEV(0, 0, 0);
39 dev <= PCI_DEV(0xff, 0x1f, 0x7);
40 dev += PCI_DEV(0,0,1)) {
41 u32 id;
42 id = pci_read_config32(dev, PCI_VENDOR_ID);
43 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
44 (((id >> 16) & 0xffff) == 0xffff) ||
45 (((id >> 16) & 0xffff) == 0x0000)) {
46 continue;
47 }
48 print_debug_pci_dev(dev);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000049 printk(BIOS_DEBUG, " %04x:%04x\n", (id & 0xffff), (id>>16));
Marc Jones8ae8c882007-12-19 01:32:08 +000050 if(((dev>>12) & 0x07) == 0) {
51 u8 hdr_type;
52 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
53 if((hdr_type & 0x80) != 0x80) {
54 dev += PCI_DEV(0,0,7);
55 }
56 }
57 }
58}
59
Stefan Reinauer8b547b12010-03-30 09:56:35 +000060static inline void print_pci_devices_on_bus(u32 busn)
Marc Jones8ae8c882007-12-19 01:32:08 +000061{
62 device_t dev;
63 for(dev = PCI_DEV(busn, 0, 0);
64 dev <= PCI_DEV(busn, 0x1f, 0x7);
65 dev += PCI_DEV(0,0,1)) {
66 u32 id;
67 id = pci_read_config32(dev, PCI_VENDOR_ID);
68 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
69 (((id >> 16) & 0xffff) == 0xffff) ||
70 (((id >> 16) & 0xffff) == 0x0000)) {
71 continue;
72 }
73 print_debug_pci_dev(dev);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000074 printk(BIOS_DEBUG, " %04x:%04x\n", (id & 0xffff), (id>>16));
Marc Jones8ae8c882007-12-19 01:32:08 +000075 if(((dev>>12) & 0x07) == 0) {
76 u8 hdr_type;
77 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
78 if((hdr_type & 0x80) != 0x80) {
79 dev += PCI_DEV(0,0,7);
80 }
81 }
82 }
83}
84
Marc Jones8ae8c882007-12-19 01:32:08 +000085static void dump_pci_device_range(u32 dev, u32 start_reg, u32 size)
86{
87 int i;
88 print_debug_pci_dev(dev);
89 int j;
90 int end = start_reg + size;
91
92 for(i = start_reg; i < end; i+=4) {
93 u32 val;
94 if ((i & 0x0f) == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000095 printk(BIOS_DEBUG, "\n%04x:",i);
Marc Jones8ae8c882007-12-19 01:32:08 +000096 }
97 val = pci_read_config32(dev, i);
98 for(j=0;j<4;j++) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000099 printk(BIOS_DEBUG, " %02x", val & 0xff);
Marc Jones8ae8c882007-12-19 01:32:08 +0000100 val >>= 8;
101 }
102 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800103 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000104}
Myles Watson075fbe82010-04-15 05:19:29 +0000105
Marc Jones8ae8c882007-12-19 01:32:08 +0000106static void dump_pci_device(u32 dev)
107{
108 dump_pci_device_range(dev, 0, 4096);
109}
Myles Watson075fbe82010-04-15 05:19:29 +0000110
Marc Jones8ae8c882007-12-19 01:32:08 +0000111static void dump_pci_device_index_wait_range(u32 dev, u32 index_reg, u32 start,
112 u32 size)
113{
114 int i;
115 int end = start + size;
116 print_debug_pci_dev(dev);
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800117 printk(BIOS_DEBUG, " -- index_reg=%08x", index_reg);
Marc Jones8ae8c882007-12-19 01:32:08 +0000118
119 for(i = start; i < end; i++) {
120 u32 val;
121 int j;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000122 printk(BIOS_DEBUG, "\n%02x:",i);
Marc Jones8ae8c882007-12-19 01:32:08 +0000123 val = pci_read_config32_index_wait(dev, index_reg, i);
124 for(j=0;j<4;j++) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000125 printk(BIOS_DEBUG, " %02x", val & 0xff);
Marc Jones8ae8c882007-12-19 01:32:08 +0000126 val >>= 8;
127 }
128
129 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800130 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000131}
Myles Watson075fbe82010-04-15 05:19:29 +0000132
Stefan Reinauer8b547b12010-03-30 09:56:35 +0000133static inline void dump_pci_device_index_wait(u32 dev, u32 index_reg)
Marc Jones8ae8c882007-12-19 01:32:08 +0000134{
135 dump_pci_device_index_wait_range(dev, index_reg, 0, 0x54);
136 dump_pci_device_index_wait_range(dev, index_reg, 0x100, 0x08); //DIMM1 when memclk > 400Hz
137// dump_pci_device_index_wait_range(dev, index_reg, 0x200, 0x08); //DIMM2
138// dump_pci_device_index_wait_range(dev, index_reg, 0x300, 0x08); //DIMM3
Marc Jones8ae8c882007-12-19 01:32:08 +0000139}
140
Stefan Reinauer8b547b12010-03-30 09:56:35 +0000141static inline void dump_pci_device_index(u32 dev, u32 index_reg, u32 type, u32 length)
Marc Jones8ae8c882007-12-19 01:32:08 +0000142{
143 int i;
144 print_debug_pci_dev(dev);
145
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800146 printk(BIOS_DEBUG, " index reg: %04x type: %02x", index_reg, type);
Marc Jones8ae8c882007-12-19 01:32:08 +0000147
148 type<<=28;
149
150 for(i = 0; i < length; i++) {
151 u32 val;
152 if ((i & 0x0f) == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000153 printk(BIOS_DEBUG, "\n%02x:",i);
Marc Jones8ae8c882007-12-19 01:32:08 +0000154 }
155 val = pci_read_config32_index(dev, index_reg, i|type);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000156 printk(BIOS_DEBUG, " %08x", val);
Marc Jones8ae8c882007-12-19 01:32:08 +0000157 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800158 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000159}
160
Stefan Reinauer8b547b12010-03-30 09:56:35 +0000161static inline void dump_pci_devices(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000162{
163 device_t dev;
164 for(dev = PCI_DEV(0, 0, 0);
165 dev <= PCI_DEV(0xff, 0x1f, 0x7);
166 dev += PCI_DEV(0,0,1)) {
167 u32 id;
168 id = pci_read_config32(dev, PCI_VENDOR_ID);
169 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
170 (((id >> 16) & 0xffff) == 0xffff) ||
171 (((id >> 16) & 0xffff) == 0x0000)) {
172 continue;
173 }
174 dump_pci_device(dev);
175
176 if(((dev>>12) & 0x07) == 0) {
177 u8 hdr_type;
178 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
179 if((hdr_type & 0x80) != 0x80) {
180 dev += PCI_DEV(0,0,7);
181 }
182 }
183 }
184}
185
Stefan Reinauer8b547b12010-03-30 09:56:35 +0000186static inline void dump_pci_devices_on_bus(u32 busn)
Marc Jones8ae8c882007-12-19 01:32:08 +0000187{
188 device_t dev;
189 for(dev = PCI_DEV(busn, 0, 0);
190 dev <= PCI_DEV(busn, 0x1f, 0x7);
191 dev += PCI_DEV(0,0,1)) {
192 u32 id;
193 id = pci_read_config32(dev, PCI_VENDOR_ID);
194 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
195 (((id >> 16) & 0xffff) == 0xffff) ||
196 (((id >> 16) & 0xffff) == 0x0000)) {
197 continue;
198 }
199 dump_pci_device(dev);
200
201 if(((dev>>12) & 0x07) == 0) {
202 u8 hdr_type;
203 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
204 if((hdr_type & 0x80) != 0x80) {
205 dev += PCI_DEV(0,0,7);
206 }
207 }
208 }
209}
210
Uwe Hermann01ce6012010-03-05 10:03:50 +0000211#if CONFIG_DEBUG_SMBUS
Marc Jones8ae8c882007-12-19 01:32:08 +0000212
213static void dump_spd_registers(const struct mem_controller *ctrl)
214{
215 int i;
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800216 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000217 for(i = 0; i < DIMM_SOCKETS; i++) {
218 u32 device;
219 device = ctrl->spd_addr[i];
220 if (device) {
221 int j;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000222 printk(BIOS_DEBUG, "dimm: %02x.0: %02x", i, device);
Marc Jones8ae8c882007-12-19 01:32:08 +0000223 for(j = 0; j < 128; j++) {
224 int status;
225 u8 byte;
226 if ((j & 0xf) == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000227 printk(BIOS_DEBUG, "\n%02x: ", j);
Marc Jones8ae8c882007-12-19 01:32:08 +0000228 }
229 status = smbus_read_byte(device, j);
230 if (status < 0) {
231 break;
232 }
233 byte = status & 0xff;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000234 printk(BIOS_DEBUG, "%02x ", byte);
Marc Jones8ae8c882007-12-19 01:32:08 +0000235 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800236 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000237 }
238 device = ctrl->spd_addr[i+DIMM_SOCKETS];
239 if (device) {
240 int j;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000241 printk(BIOS_DEBUG, "dimm: %02x.1: %02x", i, device);
Marc Jones8ae8c882007-12-19 01:32:08 +0000242 for(j = 0; j < 128; j++) {
243 int status;
244 u8 byte;
245 if ((j & 0xf) == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000246 printk(BIOS_DEBUG, "\n%02x: ", j);
Marc Jones8ae8c882007-12-19 01:32:08 +0000247 }
248 status = smbus_read_byte(device, j);
249 if (status < 0) {
250 break;
251 }
252 byte = status & 0xff;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000253 printk(BIOS_DEBUG, "%02x ", byte);
Marc Jones8ae8c882007-12-19 01:32:08 +0000254 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800255 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000256 }
257 }
258}
259static void dump_smbus_registers(void)
260{
261 u32 device;
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800262 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000263 for(device = 1; device < 0x80; device++) {
264 int j;
265 if( smbus_read_byte(device, 0) < 0 ) continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000266 printk(BIOS_DEBUG, "smbus: %02x", device);
Marc Jones8ae8c882007-12-19 01:32:08 +0000267 for(j = 0; j < 256; j++) {
268 int status;
269 u8 byte;
270 status = smbus_read_byte(device, j);
271 if (status < 0) {
272 break;
273 }
274 if ((j & 0xf) == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000275 printk(BIOS_DEBUG, "\n%02x: ",j);
Marc Jones8ae8c882007-12-19 01:32:08 +0000276 }
277 byte = status & 0xff;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000278 printk(BIOS_DEBUG, "%02x ", byte);
Marc Jones8ae8c882007-12-19 01:32:08 +0000279 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800280 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000281 }
282}
283#endif
Stefan Reinauer8b547b12010-03-30 09:56:35 +0000284static inline void dump_io_resources(u32 port)
Marc Jones8ae8c882007-12-19 01:32:08 +0000285{
286
287 int i;
Stefan Reinauer2d85fbed2010-04-14 15:44:21 +0000288 udelay(2000);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000289 printk(BIOS_DEBUG, "%04x:\n", port);
Marc Jones8ae8c882007-12-19 01:32:08 +0000290 for(i=0;i<256;i++) {
291 u8 val;
292 if ((i & 0x0f) == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000293 printk(BIOS_DEBUG, "%02x:", i);
Marc Jones8ae8c882007-12-19 01:32:08 +0000294 }
295 val = inb(port);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000296 printk(BIOS_DEBUG, " %02x",val);
Marc Jones8ae8c882007-12-19 01:32:08 +0000297 if ((i & 0x0f) == 0x0f) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800298 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000299 }
300 port++;
301 }
302}
303
Stefan Reinauer8b547b12010-03-30 09:56:35 +0000304static inline void dump_mem(u32 start, u32 end)
Marc Jones8ae8c882007-12-19 01:32:08 +0000305{
306 u32 i;
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800307 printk(BIOS_DEBUG, "dump_mem:");
Marc Jones8ae8c882007-12-19 01:32:08 +0000308 for(i=start;i<end;i++) {
309 if((i & 0xf)==0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000310 printk(BIOS_DEBUG, "\n%08x:", i);
Marc Jones8ae8c882007-12-19 01:32:08 +0000311 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000312 printk(BIOS_DEBUG, " %02x", (u8)*((u8 *)i));
Marc Jones8ae8c882007-12-19 01:32:08 +0000313 }
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800314 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000315}