blob: ee45c65f0716e30d0a220dfd02ec1601e0b2178e [file] [log] [blame]
Stefan Reinauerf622d592005-11-26 16:56:05 +00001/*
Frank Vibransc282a182010-06-04 07:49:53 +00002 * This file is part of the coreboot project.
3 *
Uwe Hermannc6a10622010-10-17 19:30:58 +00004 * Copyright (C) 2005,2010 Advanced Micro Devices, Inc.
Frank Vibransc282a182010-06-04 07:49:53 +00005 *
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; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Frank Vibransc282a182010-06-04 07:49:53 +000015 */
16
Stefan Reinauerf622d592005-11-26 16:56:05 +000017#include <console/console.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pci_ids.h>
21#include <device/pci_ops.h>
22#include <pc80/mc146818rtc.h>
23#include <device/pci_def.h>
24#include <device/pcix.h>
25
26#define NMI_OFF 0
27
28#define NPUML 0xD9 /* Non prefetchable upper memory limit */
29#define NPUMB 0xD8 /* Non prefetchable upper memory base */
30
31static void amd8132_walk_children(struct bus *bus,
32 void (*visit)(device_t dev, void *ptr), void *ptr)
33{
34 device_t child;
35 for(child = bus->children; child; child = child->sibling)
36 {
37 if (child->path.type != DEVICE_PATH_PCI) {
38 continue;
39 }
40 if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
Myles Watson894a3472010-06-09 22:41:35 +000041 amd8132_walk_children(child->link_list, visit, ptr);
Stefan Reinauerf622d592005-11-26 16:56:05 +000042 }
43 visit(child, ptr);
44 }
45}
46
47struct amd8132_bus_info {
48 unsigned sstatus;
49 unsigned rev;
50 int master_devices;
51 int max_func;
52};
53
54static void amd8132_count_dev(device_t dev, void *ptr)
55{
56 struct amd8132_bus_info *info = ptr;
57 /* Don't count pci bridges */
58 if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
59 info->master_devices++;
60 }
Stefan Reinauer2b34db82009-02-28 20:10:20 +000061 if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) {
62 info->max_func = PCI_FUNC(dev->path.pci.devfn);
Stefan Reinauerf622d592005-11-26 16:56:05 +000063 }
64}
65
66
67static void amd8132_pcix_tune_dev(device_t dev, void *ptr)
68{
69 struct amd8132_bus_info *info = ptr;
70 unsigned cap;
71 unsigned status, cmd, orig_cmd;
72 unsigned max_read, max_tran;
73 int sibs;
74
75 if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) {
76 return;
77 }
78 cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
79 if (!cap) {
80 return;
81 }
82 /* How many siblings does this device have? */
83 sibs = info->master_devices - 1;
84
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000085 printk(BIOS_DEBUG, "%s AMD8132 PCI-X tuning\n", dev_path(dev));
Stefan Reinauerf622d592005-11-26 16:56:05 +000086 status = pci_read_config32(dev, cap + PCI_X_STATUS);
87 orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD);
88
89 max_read = (status & PCI_X_STATUS_MAX_READ) >> 21;
90 max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23;
91
Stefan Reinauer14e22772010-04-27 06:56:47 +000092 if (info->rev == 0x01) { // only a1 need it
Stefan Reinauerf622d592005-11-26 16:56:05 +000093 /* Errata #53 Limit the number of split transactions to avoid starvation */
94 if (sibs >= 2) {
95 /* At most 2 outstanding split transactions when we have
96 * 3 or more bus master devices on the bus.
97 */
98 if (max_tran > 1) {
99 max_tran = 1;
100 }
101 }
102 else if (sibs == 1) {
103 /* At most 4 outstanding split transactions when we have
104 * 2 bus master devices on the bus.
105 */
106 if (max_tran > 3) {
107 max_tran = 3;
108 }
109 }
110 else {
111 /* At most 8 outstanding split transactions when we have
112 * only one bus master device on the bus.
113 */
114 if (max_tran > 4) {
115 max_tran = 4;
116 }
117 }
118 }
119
120 if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) {
121 cmd &= ~PCI_X_CMD_MAX_READ;
122 cmd |= max_read << 2;
123 }
124 if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) {
125 cmd &= ~PCI_X_CMD_MAX_SPLIT;
126 cmd |= max_tran << 4;
127 }
128
129 /* Don't attempt to handle PCI-X errors */
130 cmd &= ~PCI_X_CMD_DPERR_E;
131 if (orig_cmd != cmd) {
132 pci_write_config16(dev, cap + PCI_X_CMD, cmd);
133 }
134
135
136}
Kyösti Mälkkide271a82015-03-18 13:09:47 +0200137static void amd8132_scan_bus(struct bus *bus,
138 unsigned min_devfn, unsigned max_devfn)
Stefan Reinauerf622d592005-11-26 16:56:05 +0000139{
140 struct amd8132_bus_info info;
141 unsigned pos;
142
Stefan Reinauerf622d592005-11-26 16:56:05 +0000143 /* Find the children on the bus */
Kyösti Mälkkide271a82015-03-18 13:09:47 +0200144 pci_scan_bus(bus, min_devfn, max_devfn);
Stefan Reinauerf622d592005-11-26 16:56:05 +0000145
146 /* Find the revision of the 8132 */
147 info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION);
148
149 /* Find the pcix capability and get the secondary bus status */
150 pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX);
151 info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS);
152
153 /* Print the PCI-X bus speed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000154 printk(BIOS_DEBUG, "PCI: %02x: %s sstatus=%04x rev=%02x \n", bus->secondary, pcix_speed(info.sstatus), info.sstatus, info.rev);
Stefan Reinauerf622d592005-11-26 16:56:05 +0000155
156
157 /* Examine the bus and find out how loaded it is */
158 info.max_func = 0;
159 info.master_devices = 0;
160 amd8132_walk_children(bus, amd8132_count_dev, &info);
161
162#if 0
Stefan Reinauer14e22772010-04-27 06:56:47 +0000163 /* Disable the bus if there are no devices on it
Stefan Reinauerf622d592005-11-26 16:56:05 +0000164 */
165 if (!bus->children)
166 {
167 unsigned pcix_misc;
168 /* Disable all of my children */
169 disable_children(bus);
170
171 /* Remember the device is disabled */
172 bus->dev->enabled = 0;
173
174 /* Disable the PCI-X clocks */
175 pcix_misc = pci_read_config32(bus->dev, 0x40);
176 pcix_misc &= ~(0x1f << 16);
177 pci_write_config32(bus->dev, 0x40, pcix_misc);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000178
Kyösti Mälkkide271a82015-03-18 13:09:47 +0200179 return;
Stefan Reinauerf622d592005-11-26 16:56:05 +0000180 }
181#endif
182
183 /* If we are in conventional PCI mode nothing more is necessary.
184 */
185 if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) {
Kyösti Mälkkide271a82015-03-18 13:09:47 +0200186 return;
Stefan Reinauerf622d592005-11-26 16:56:05 +0000187 }
188
189 /* Tune the devices on the bus */
190 amd8132_walk_children(bus, amd8132_pcix_tune_dev, &info);
Stefan Reinauerf622d592005-11-26 16:56:05 +0000191}
192
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200193static void amd8132_scan_bridge(device_t dev)
Stefan Reinauerf622d592005-11-26 16:56:05 +0000194{
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200195 do_pci_scan_bridge(dev, amd8132_scan_bus);
Stefan Reinauerf622d592005-11-26 16:56:05 +0000196}
197
198
199static void amd8132_pcix_init(device_t dev)
200{
201 uint32_t dword;
202 uint8_t byte;
203 unsigned chip_rev;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000204
Stefan Reinauerf622d592005-11-26 16:56:05 +0000205 /* Find the revision of the 8132 */
206 chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION);
207
208 /* Enable memory write and invalidate ??? */
209 dword = pci_read_config32(dev, 0x04);
210 dword |= 0x10;
211 dword &= ~(1<<6); // PERSP Parity Error Response
212 pci_write_config32(dev, 0x04, dword);
213
214 if (chip_rev == 0x01) {
215 /* Errata #37 */
216 byte = pci_read_config8(dev, 0x0c);
217 if(byte == 0x08 )
218 pci_write_config8(dev, 0x0c, 0x10);
219
220#if 0
221 /* Errata #59*/
222 dword = pci_read_config32(dev, 0x40);
223 dword &= ~(1<<31);
224 pci_write_config32(dev, 0x40, dword);
225#endif
226
227 }
228
229 /* Set up error reporting, enable all */
230 /* system error enable */
231 dword = pci_read_config32(dev, 0x04);
232 dword |= (1<<8);
233 pci_write_config32(dev, 0x04, dword);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000234
Stefan Reinauerf622d592005-11-26 16:56:05 +0000235 /* system and error parity enable */
236 dword = pci_read_config32(dev, 0x3c);
237 dword |= (3<<16);
238 pci_write_config32(dev, 0x3c, dword);
239
240 dword = pci_read_config32(dev, 0x40);
241// dword &= ~(1<<31); /* WriteChainEnable */
Stefan Reinauer14e22772010-04-27 06:56:47 +0000242 dword |= (1<<31);
Stefan Reinauerf622d592005-11-26 16:56:05 +0000243 dword |= (1<<7);// must set to 1
244 dword |= (3<<21); //PCIErrorSerrDisable
245 pci_write_config32(dev, 0x40, dword);
246
247 /* EXTARB = 1, COMPAT = 0 */
248 dword = pci_read_config32(dev, 0x48);
249 dword |= (1<<3);
250 dword &= ~(1<<0);
251 dword |= (1<<15); //CLEARPCILOG_L
252 dword |= (1<<19); //PERR FATAL Enable
253 dword |= (1<<22); // SERR FATAL Enable
254 dword |= (1<<23); // LPMARBENABLE
255 dword |= (0x61<<24); //LPMARBCOUNT
256 pci_write_config32(dev, 0x48, dword);
257
258 dword = pci_read_config32(dev, 0x4c);
Martin Roth55e31a92014-12-16 20:53:49 -0700259 dword |= (1<<6); //Initial prefetch for memory read line request
Stefan Reinauerf622d592005-11-26 16:56:05 +0000260 dword |= (1<<9); //continuous prefetch Enable for memory read line request
261 pci_write_config32(dev, 0x4c, dword);
262
263
264 /* Disable Single-Bit-Error Correction [30] = 0 */
265 dword = pci_read_config32(dev, 0x70);
266 dword &= ~(1<<30);
267 pci_write_config32(dev, 0x70, dword);
268
269 //link
270 dword = pci_read_config32(dev, 0xd4);
271 dword |= (0x5c<<16);
272 pci_write_config32(dev, 0xd4, dword);
273
274 /* TxSlack0 [16:17] = 0, RxHwLookahdEn0 [18] = 1, TxSlack1 [24:25] = 0, RxHwLookahdEn1 [26] = 1 */
275 dword = pci_read_config32(dev, 0xdc);
276 dword |= (1<<1) | (1<<4); // stream disable 1 to 0 , DBLINSRATE
277 dword |= (1<<18)|(1<<26);
278 dword &= ~((3<<16)|(3<<24));
279 pci_write_config32(dev, 0xdc, dword);
280
281 /* Set up CRC flood enable */
282 dword = pci_read_config32(dev, 0xc0);
283 if(dword) { /* do device A only */
284#if 0
285 dword = pci_read_config32(dev, 0xc4);
286 dword |= (1<<1);
287 pci_write_config32(dev, 0xc4, dword);
288 dword = pci_read_config32(dev, 0xc8);
289 dword |= (1<<1);
290 pci_write_config32(dev, 0xc8, dword);
291#endif
292
293 if (chip_rev == 0x11) {
294 /* [18] Clock Gate Enable = 1 */
295 dword = pci_read_config32(dev, 0xf0);
296 dword |= 0x00040008;
297 pci_write_config32(dev, 0xf0, dword);
298 }
299
300 }
301 return;
302}
303
304#define BRIDGE_40_BIT_SUPPORT 0
305#if BRIDGE_40_BIT_SUPPORT
306static void bridge_read_resources(struct device *dev)
307{
308 struct resource *res;
309 pci_bus_read_resources(dev);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000310 res = find_resource(dev, PCI_MEMORY_BASE);
Stefan Reinauerf622d592005-11-26 16:56:05 +0000311 if (res) {
312 res->limit = 0xffffffffffULL;
313 }
314}
315
316static void bridge_set_resources(struct device *dev)
317{
318 struct resource *res;
319 res = find_resource(dev, PCI_MEMORY_BASE);
320 if (res) {
321 resource_t base, end;
322 /* set the memory range */
323 dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
324 res->flags |= IORESOURCE_STORED;
Stefan Reinauerf622d592005-11-26 16:56:05 +0000325 base = res->base;
326 end = resource_end(res);
327 pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
328 pci_write_config8(dev, NPUML, (base >> 32) & 0xff);
329 pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
330 pci_write_config8(dev, NPUMB, (end >> 32) & 0xff);
331
332 report_resource_stored(dev, res, "");
333 }
334 pci_dev_set_resources(dev);
335}
336#endif /* BRIDGE_40_BIT_SUPPORT */
337
338static struct device_operations pcix_ops = {
339#if BRIDGE_40_BIT_SUPPORT
340 .read_resources = bridge_read_resources,
341 .set_resources = bridge_set_resources,
342#else
343 .read_resources = pci_bus_read_resources,
344 .set_resources = pci_dev_set_resources,
345#endif
346 .enable_resources = pci_bus_enable_resources,
347 .init = amd8132_pcix_init,
348 .scan_bus = amd8132_scan_bridge,
349 .reset_bus = pci_bus_reset,
350};
351
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000352static const struct pci_driver pcix_driver __pci_driver = {
Stefan Reinauerf622d592005-11-26 16:56:05 +0000353 .ops = &pcix_ops,
354 .vendor = PCI_VENDOR_ID_AMD,
355 .device = 0x7458,
356};
357
358static void ioapic_enable(device_t dev)
359{
360 uint32_t value;
361
362 value = pci_read_config32(dev, 0x44);
363 if (dev->enabled) {
364 value |= ((1 << 1) | (1 << 0));
365 } else {
366 value &= ~((1 << 1) | (1 << 0));
367 }
368 pci_write_config32(dev, 0x44, value);
369}
370static void amd8132_ioapic_init(device_t dev)
371{
372 uint32_t dword;
373 unsigned chip_rev;
374
375 /* Find the revision of the 8132 */
376 chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION);
377
378 if (chip_rev == 0x01) {
379#if 0
380 /* Errata #43 */
381 dword = pci_read_config32(dev, 0xc8);
382 dword |= (0x3<<23);
383 pci_write_config32(dev, 0xc8, dword);
384#endif
385
386 }
387
388
389 if( (chip_rev == 0x11) ||(chip_rev == 0x12) ) {
390 //for b1 b2
391 /* Errata #73 */
392 dword = pci_read_config32(dev, 0x80);
393 dword |= (0x1f<<5);
394 pci_write_config32(dev, 0x80, dword);
395 dword = pci_read_config32(dev, 0x88);
396 dword |= (0x1f<<5);
397 pci_write_config32(dev, 0x88, dword);
398
399 /* Errata #74 */
400 dword = pci_read_config32(dev, 0x7c);
401 dword &= ~(0x3<<30);
402 dword |= (0x01<<30);
403 pci_write_config32(dev, 0x7c, dword);
404 }
405
406}
407
408static struct pci_operations pci_ops_pci_dev = {
409 .set_subsystem = pci_dev_set_subsystem,
410};
411static struct device_operations ioapic_ops = {
412 .read_resources = pci_dev_read_resources,
413 .set_resources = pci_dev_set_resources,
414 .enable_resources = pci_dev_enable_resources,
415 .init = amd8132_ioapic_init,
416 .scan_bus = 0,
417 .enable = ioapic_enable,
418 .ops_pci = &pci_ops_pci_dev,
419};
420
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000421static const struct pci_driver ioapic_driver __pci_driver = {
Stefan Reinauerf622d592005-11-26 16:56:05 +0000422 .ops = &ioapic_ops,
423 .vendor = PCI_VENDOR_ID_AMD,
424 .device = 0x7459,
Stefan Reinauer14e22772010-04-27 06:56:47 +0000425
Stefan Reinauerf622d592005-11-26 16:56:05 +0000426};