blob: 818b0e646c25776bff032001c29dbe41229ba792 [file] [log] [blame]
Zheng Bao98fcc092011-03-27 16:39:58 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
Timothy Pearsonc3fcdcc2015-09-05 17:46:38 -05005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Zheng Bao98fcc092011-03-27 16:39:58 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
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.
Zheng Bao98fcc092011-03-27 16:39:58 +000015 */
16
17#include <console/console.h>
18#include <arch/io.h>
19#include <device/device.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <device/pci_ops.h>
23#include <cpu/x86/msr.h>
24#include <cpu/amd/mtrr.h>
Timothy Pearson44e4a4e2015-08-11 17:49:06 -050025#include <stdlib.h>
Zheng Bao98fcc092011-03-27 16:39:58 +000026#include <delay.h>
Timothy Pearson44e4a4e2015-08-11 17:49:06 -050027#include <option.h>
Zheng Bao98fcc092011-03-27 16:39:58 +000028#include "sr5650.h"
29#include "cmn.h"
30
31/*
32 * extern function declaration
33 */
34extern void set_pcie_dereset(void);
35extern void set_pcie_reset(void);
36
Timothy Pearson1eaaa0e2015-08-14 15:20:42 -050037struct resource * sr5650_retrieve_cpu_mmio_resource() {
Timothy Pearson77133af2016-01-01 23:30:42 -060038 device_t domain;
Timothy Pearson1eaaa0e2015-08-14 15:20:42 -050039 struct resource *res;
40
Timothy Pearson77133af2016-01-01 23:30:42 -060041 for (domain = all_devices; domain; domain = domain->next) {
42 if (domain->bus->dev->path.type != DEVICE_PATH_DOMAIN)
Timothy Pearson1eaaa0e2015-08-14 15:20:42 -050043 continue;
Timothy Pearson77133af2016-01-01 23:30:42 -060044 res = probe_resource(domain->bus->dev, 0xc0010058);
Timothy Pearson1eaaa0e2015-08-14 15:20:42 -050045 if (res)
46 return res;
47 }
48
49 return NULL;
50}
51
Zheng Bao98fcc092011-03-27 16:39:58 +000052/* extension registers */
53u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg)
54{
55 /*get BAR3 base address for nbcfg0x1c */
56 u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF;
57 printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary,
58 dev->path.pci.devfn);
59 addr |= dev->bus->secondary << 20 | /* bus num */
60 dev->path.pci.devfn << 12 | reg;
61 return *((u32 *) addr);
62}
63
64void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val)
65{
66 u32 reg_old, reg;
67
68 /*get BAR3 base address for nbcfg0x1c */
69 u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF;
70 /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary,
71 dev->path.pci.devfn);*/
72 addr |= dev->bus->secondary << 20 | /* bus num */
73 dev->path.pci.devfn << 12 | reg_pos;
74
75 reg = reg_old = *((u32 *) addr);
76 reg &= ~mask;
77 reg |= val;
78 if (reg != reg_old) {
79 *((u32 *) addr) = reg;
80 }
81}
82
83u32 nbpcie_p_read_index(device_t dev, u32 index)
84{
85 return nb_read_index((dev), NBPCIE_INDEX, (index));
86}
87
88void nbpcie_p_write_index(device_t dev, u32 index, u32 data)
89{
90 nb_write_index((dev), NBPCIE_INDEX, (index), (data));
91}
92
93u32 nbpcie_ind_read_index(device_t nb_dev, u32 index)
94{
95 return nb_read_index((nb_dev), NBPCIE_INDEX, (index));
96}
97
98void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data)
99{
100 nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data));
101}
102
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500103uint32_t l2cfg_ind_read_index(device_t nb_dev, uint32_t index)
104{
105 return nb_read_index((nb_dev), L2CFG_INDEX, (index));
106}
107
108void l2cfg_ind_write_index(device_t nb_dev, uint32_t index, uint32_t data)
109{
110 nb_write_index((nb_dev), L2CFG_INDEX | (0x1 << 8), (index), (data));
111}
112
113uint32_t l1cfg_ind_read_index(device_t nb_dev, uint32_t index)
114{
115 return nb_read_index((nb_dev), L1CFG_INDEX, (index));
116}
117
118void l1cfg_ind_write_index(device_t nb_dev, uint32_t index, uint32_t data)
119{
120 nb_write_index((nb_dev), L1CFG_INDEX | (0x1 << 31), (index), (data));
121}
122
Zheng Bao98fcc092011-03-27 16:39:58 +0000123/***********************************************************
124* To access bar3 we need to program PCI MMIO 7 in K8.
125* in_out:
126* 1: enable/enter k8 temp mmio base
127* 0: disable/restore
128***********************************************************/
129void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add)
130{
131 /* K8 Function1 is address map */
Timothy Pearsonc3fcdcc2015-09-05 17:46:38 -0500132 device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
133 device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
Zheng Bao98fcc092011-03-27 16:39:58 +0000134
Timothy Pearsonc3fcdcc2015-09-05 17:46:38 -0500135 if (in_out) {
136 u32 dword, sblk;
Zheng Bao98fcc092011-03-27 16:39:58 +0000137
Timothy Pearsonc3fcdcc2015-09-05 17:46:38 -0500138 /* Get SBLink value (HyperTransport I/O Hub Link ID). */
139 dword = pci_read_config32(k8_f0, 0x64);
140 sblk = (dword >> 8) & 0x3;
141
142 /* Fill MMIO limit/base pair. */
143 pci_write_config32(k8_f1, 0xbc,
144 (((pcie_base_add + 0x10000000 -
145 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4));
146 pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3);
147 pci_write_config32(k8_f1, 0xb4,
148 (((mmio_base_add + 0x10000000 -
149 1) >> 8) & 0xffffff00) | (sblk << 4));
150 pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3);
151 } else {
152 pci_write_config32(k8_f1, 0xb8, 0);
153 pci_write_config32(k8_f1, 0xbc, 0);
154 pci_write_config32(k8_f1, 0xb0, 0);
155 pci_write_config32(k8_f1, 0xb4, 0);
Zheng Bao98fcc092011-03-27 16:39:58 +0000156 }
157}
158
159void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port)
160{
161 switch (port) {
162 case 2: /* GPP1, bit4-5 */
163 case 3:
164 set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG,
165 1 << (port + 2), 0 << (port + 2));
166 break;
167 case 4: /* GPP3a, bit20-24 */
168 case 5:
169 case 6:
170 case 7:
171 set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG,
172 1 << (port + 17), 0 << (port + 17));
173 break;
174 case 9: /* GPP3a, bit25,26 */
175 case 10:
176 set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG,
177 1 << (port + 16), 0 << (port + 16));
178 break;
179 case 11: /* GPP2, bit6-7 */
180 case 12:
181 set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG,
182 1 << (port - 5), 0 << (port - 5));
183 break;
184 case 13: /* GPP3b, bit4 of NBMISCIND:0x2A */
185 set_nbmisc_enable_bits(nb_dev, 0x2A,
186 1 << 4, 0 << 4);
187 break;
188 }
189}
190
191/********************************************************************************************************
192* Output:
193* 0: no device is present.
194* 1: device is present and is trained.
195********************************************************************************************************/
196u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port)
197{
198 u16 count = 5000;
199 u32 lc_state, reg, current_link_width, lane_mask;
200 u8 current, res = 0;
201 u32 gpp_sb_sel = 0;
202
203 switch (port) {
204 case 2:
205 case 3:
206 gpp_sb_sel = PCIE_CORE_INDEX_GPP1;
207 break;
208 case 4 ... 7:
209 case 9:
210 case 10:
211 gpp_sb_sel = PCIE_CORE_INDEX_GPP3a;
212 break;
213 case 11:
214 case 12:
215 gpp_sb_sel = PCIE_CORE_INDEX_GPP2;
216 break;
217 case 13:
218 gpp_sb_sel = PCIE_CORE_INDEX_GPP3b;
219 break;
220 }
221
222 while (count--) {
223 udelay(40200);
224 lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */
225 printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n",
226 port, lc_state);
227 current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */
228
229 switch (current) {
230 /* 0x00-0x04 means no device is present */
231 case 0x06:
232 /* read back current link width [6:4]. */
233 current_link_width = (nbpcie_p_read_index(dev, 0xA2) >> 4) & 0x7;
234 /* 4 means 7:4 and 15:12
235 * 3 means 7:2 and 15:10
236 * 2 means 7:1 and 15:9
Paul Menzel6a121092013-04-10 11:33:37 +0200237 * ignoring the reversal case
Zheng Bao98fcc092011-03-27 16:39:58 +0000238 */
239 lane_mask = (0xFF << (current_link_width - 2) * 2) & 0xFF;
240 reg = nbpcie_ind_read_index(nb_dev, 0x65 | gpp_sb_sel);
241 reg |= lane_mask << 8 | lane_mask;
242 /* NOTE: See the comments in rs780_pcie.c
243 * switching_gppsb_configurations
244 * In CIMx 4.5.0 and RPR, 4c is done before 5 & 6.
245 * But in this way, a x4 device in port B (dev 4) of
246 * Configuration B can only be detected as x1, instead
247 * of x4. When the port B is being trained, the
248 * LC_CURRENT_STATE is 6 and the LC_LINK_WIDTH_RD is 1.
249 * We have to set the PCIEIND:0x65 as 0xE0E0 and reset
250 * the slot. Then the card seems to work in x1 mode.
251 */
252 reg = 0xE0E0; /*I think that the lane_mask calc above is wrong, and this can't be hardcoded because the configuration changes.*/
253 nbpcie_ind_write_index(nb_dev, 0x65 | gpp_sb_sel, reg);
254 printk(BIOS_DEBUG, "link_width=%x, lane_mask=%x",
255 current_link_width, lane_mask);
256 set_pcie_reset();
257 mdelay(1);
258 set_pcie_dereset();
259 break;
260 case 0x07: /* device is in compliance state (training sequence is done). Move to train the next device */
261 res = 1;
262 count = 0;
263 break;
264 case 0x10:
265 reg =
266 pci_ext_read_config32(nb_dev, dev,
267 PCIE_VC0_RESOURCE_STATUS);
268 printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg);
269 /* check bit1 */
270 if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */
271 /* set bit8=1, bit0-2=bit4-6 */
272 u32 tmp;
Edward O'Callaghana9a2e102014-12-08 03:00:26 +1100273 reg = nbpcie_p_read_index(dev, PCIE_LC_LINK_WIDTH);
274 tmp = (reg >> 4) & 0x7; /* get bit4-6 */
Zheng Bao98fcc092011-03-27 16:39:58 +0000275 reg &= 0xfff8; /* clear bit0-2 */
276 reg += tmp; /* merge */
277 reg |= 1 << 8;
Edward O'Callaghana9a2e102014-12-08 03:00:26 +1100278 nbpcie_p_write_index(dev, PCIE_LC_LINK_WIDTH, reg);
Zheng Bao98fcc092011-03-27 16:39:58 +0000279 count++; /* CIM said "keep in loop"? */
280 } else {
281 res = 1;
282 count = 0;
283 }
284 break;
285 default:
286 /* CIMx Unknown Workaround - There is a device that won't train. Try to reset it. */
287 /* if there are no device resets and nothing works, CIMx does a cf9 system reset (yikes!) */
288 set_pcie_reset();
289 mdelay(1);
290 set_pcie_dereset();
291 res = 0;
292 count = 0; /* break loop */
293 break;
294 }
295 }
296 return res;
297}
298
299/*
efdesign9800c8c4a2011-07-20 12:37:58 -0600300 * Set Top Of Memory below and above 4G.
301 */
Zheng Bao98fcc092011-03-27 16:39:58 +0000302void sr5650_set_tom(device_t nb_dev)
303{
efdesign9800c8c4a2011-07-20 12:37:58 -0600304 msr_t sysmem;
Zheng Bao98fcc092011-03-27 16:39:58 +0000305
efdesign9800c8c4a2011-07-20 12:37:58 -0600306 /* The system top memory in SR56X0. */
307 sysmem = rdmsr(0xc001001A);
308 printk(BIOS_DEBUG, "Sysmem TOM = %x_%x\n", sysmem.hi, sysmem.lo);
309 pci_write_config32(nb_dev, 0x90, sysmem.lo);
310
311 sysmem = rdmsr(0xc001001D);
312 printk(BIOS_DEBUG, "Sysmem TOM2 = %x_%x\n", sysmem.hi, sysmem.lo);
313 htiu_write_index(nb_dev, 0x31, sysmem.hi);
314 htiu_write_index(nb_dev, 0x30, sysmem.lo | 1);
Zheng Bao98fcc092011-03-27 16:39:58 +0000315}
316
317u32 get_vid_did(device_t dev)
318{
319 return pci_read_config32(dev, 0);
320}
321
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500322void detect_and_enable_iommu(device_t iommu_dev) {
323 uint32_t dword;
324 uint8_t l1_target;
325 unsigned char iommu;
326 void * mmio_base;
327
328 iommu = 1;
329 get_option(&iommu, "iommu");
330
331 if (iommu) {
332 printk(BIOS_DEBUG, "Initializing IOMMU\n");
333
334 device_t nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0));
335
336 if (!nb_dev) {
337 printk(BIOS_WARNING, "Unable to find SR5690 device! IOMMU NOT initialized\n");
338 return;
339 }
340
341 mmio_base = (void*)(pci_read_config32(iommu_dev, 0x44) & 0xffffc000);
342
343 // if (get_nb_rev(nb_dev) == REV_SR5650_A11) {
344 // dword = pci_read_config32(iommu_dev, 0x6c);
345 // dword &= ~(0x1 << 8);
346 // pci_write_config32(iommu_dev, 0x6c, dword);
347 // }
348
349 dword = pci_read_config32(iommu_dev, 0x50);
350 dword &= ~(0x1 << 22);
351 pci_write_config32(iommu_dev, 0x50, dword);
352
353 dword = pci_read_config32(iommu_dev, 0x44);
354 dword |= 0x1;
355 pci_write_config32(iommu_dev, 0x44, dword);
356
357 write32((void*)(mmio_base + 0x8), 0x0);
358 write32((void*)(mmio_base + 0xc), 0x08000000);
359 write32((void*)(mmio_base + 0x10), 0x0);
360 write32((void*)(mmio_base + 0x2008), 0x0);
361 write32((void*)(mmio_base + 0x2010), 0x0);
362
363 /* IOMMU L1 initialization */
364 for (l1_target = 0; l1_target < 6; l1_target++) {
365 dword = l1cfg_ind_read_index(nb_dev, (l1_target << 16) + 0xc);
366 dword |= (0x7 << 28);
367 l1cfg_ind_write_index(nb_dev, (l1_target << 16) + 0xc, dword);
368
369 dword = l1cfg_ind_read_index(nb_dev, (l1_target << 16) + 0x7);
370 dword |= (0x1 << 5);
371 l1cfg_ind_write_index(nb_dev, (l1_target << 16) + 0x7, dword);
372 }
373
374 /* IOMMU L2 initialization */
375 dword = l2cfg_ind_read_index(nb_dev, 0xc);
376 dword |= (0x7 << 29);
377 l2cfg_ind_write_index(nb_dev, 0xc, dword);
378
379 dword = l2cfg_ind_read_index(nb_dev, 0x10);
380 dword &= ~(0x3 << 8);
381 dword |= (0x2 << 8);
382 l2cfg_ind_write_index(nb_dev, 0x10, dword);
383
384 dword = l2cfg_ind_read_index(nb_dev, 0x14);
385 dword &= ~(0x3 << 8);
386 dword |= (0x2 << 8);
387 l2cfg_ind_write_index(nb_dev, 0x14, dword);
388
389 dword = l2cfg_ind_read_index(nb_dev, 0x18);
390 dword &= ~(0x3 << 8);
391 dword |= (0x2 << 8);
392 l2cfg_ind_write_index(nb_dev, 0x18, dword);
393
394 dword = l2cfg_ind_read_index(nb_dev, 0x1c);
395 dword &= ~(0x3 << 8);
396 dword |= (0x2 << 8);
397 l2cfg_ind_write_index(nb_dev, 0x1c, dword);
398
399 dword = l2cfg_ind_read_index(nb_dev, 0x50);
400 dword &= ~(0x3 << 8);
401 dword |= (0x2 << 8);
402 l2cfg_ind_write_index(nb_dev, 0x50, dword);
403
404 dword = l2cfg_ind_read_index(nb_dev, 0x10);
405 dword |= (0x1 << 4);
406 l2cfg_ind_write_index(nb_dev, 0x10, dword);
407
408 dword = l2cfg_ind_read_index(nb_dev, 0x14);
409 dword |= (0x1 << 4);
410 l2cfg_ind_write_index(nb_dev, 0x14, dword);
411
412 dword = l2cfg_ind_read_index(nb_dev, 0x18);
413 dword |= (0x1 << 4);
414 l2cfg_ind_write_index(nb_dev, 0x18, dword);
415
416 dword = l2cfg_ind_read_index(nb_dev, 0x1c);
417 dword |= (0x1 << 4);
418 l2cfg_ind_write_index(nb_dev, 0x1c, dword);
419
420 dword = l2cfg_ind_read_index(nb_dev, 0x50);
421 dword |= (0x1 << 4);
422 l2cfg_ind_write_index(nb_dev, 0x50, dword);
423
424 dword = l2cfg_ind_read_index(nb_dev, 0x6);
425 dword |= (0x1 << 7);
426 l2cfg_ind_write_index(nb_dev, 0x6, dword);
427
428 dword = l2cfg_ind_read_index(nb_dev, 0x44);
429 dword |= (0x1 << 0);
430 l2cfg_ind_write_index(nb_dev, 0x44, dword);
431
432// if (get_nb_rev(nb_dev) == REV_SR5650_A21) {
433 dword = l2cfg_ind_read_index(nb_dev, 0x7);
434 dword |= (0x1 << 1);
435 l2cfg_ind_write_index(nb_dev, 0x7, dword);
436
437 dword = l2cfg_ind_read_index(nb_dev, 0x44);
438 dword |= (0x1 << 1);
439 l2cfg_ind_write_index(nb_dev, 0x44, dword);
440
441 dword = l2cfg_ind_read_index(nb_dev, 0x7);
442 dword |= (0x1 << 2);
443 l2cfg_ind_write_index(nb_dev, 0x7, dword);
444
445 dword = l2cfg_ind_read_index(nb_dev, 0x7);
446 dword |= (0x1 << 3);
447 l2cfg_ind_write_index(nb_dev, 0x7, dword);
448
449 dword = l2cfg_ind_read_index(nb_dev, 0x44);
450 dword |= (0x1 << 3);
451 l2cfg_ind_write_index(nb_dev, 0x44, dword);
452
453 dword = l2cfg_ind_read_index(nb_dev, 0x7);
454 dword |= (0x1 << 4);
455 l2cfg_ind_write_index(nb_dev, 0x7, dword);
456
457 dword = l2cfg_ind_read_index(nb_dev, 0x6);
458 dword |= (0x1 << 5);
459 l2cfg_ind_write_index(nb_dev, 0x6, dword);
460
461 dword = l2cfg_ind_read_index(nb_dev, 0x6);
462 dword |= (0x1 << 6);
463 l2cfg_ind_write_index(nb_dev, 0x6, dword);
464
465 dword = l2cfg_ind_read_index(nb_dev, 0x7);
466 dword |= (0x1 << 5);
467 l2cfg_ind_write_index(nb_dev, 0x7, dword);
468
469 dword = l2cfg_ind_read_index(nb_dev, 0x44);
470 dword |= (0x1 << 4);
471 l2cfg_ind_write_index(nb_dev, 0x44, dword);
472
473 dword = l2cfg_ind_read_index(nb_dev, 0x7);
474 dword |= (0x1 << 6);
475 l2cfg_ind_write_index(nb_dev, 0x7, dword);
476
477 dword = l2cfg_ind_read_index(nb_dev, 0x7);
478 dword |= (0x1 << 7);
479 l2cfg_ind_write_index(nb_dev, 0x7, dword);
480
481 dword = l2cfg_ind_read_index(nb_dev, 0x6);
482 dword |= (0x1 << 8);
483 l2cfg_ind_write_index(nb_dev, 0x6, dword);
484// }
485
486 l2cfg_ind_write_index(nb_dev, 0x52, 0xf0000002);
487
488 dword = l2cfg_ind_read_index(nb_dev, 0x80);
489 dword |= (0x1 << 0);
490 l2cfg_ind_write_index(nb_dev, 0x80, dword);
491
492 dword = l2cfg_ind_read_index(nb_dev, 0x30);
493 dword |= (0x1 << 0);
494 l2cfg_ind_write_index(nb_dev, 0x30, dword);
495 }
496}
497
498void sr5650_iommu_read_resources(device_t dev)
499{
500 unsigned char iommu;
501 struct resource *res;
502
503 iommu = 1;
504 get_option(&iommu, "iommu");
505
506 /* Get the normal pci resources of this device */
507 pci_dev_read_resources(dev);
508
509 if (iommu) {
510 /* Request MMIO range allocation */
511 res = new_resource(dev, 0x44); /* IOMMU */
512 res->base = 0x0;
513 res->size = 0x4000;
514 res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
515 res->align = 14; /* 16k alignment */
516 res->gran = 14;
517 res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE;
518 }
519
520 compact_resources(dev);
521}
522
523void sr5650_iommu_set_resources(device_t dev)
524{
525 unsigned char iommu;
526 struct resource *res;
527
528 iommu = 1;
529 get_option(&iommu, "iommu");
530
531 /* Get the normal pci resources of this device */
532 pci_dev_read_resources(dev);
533
534 if (iommu) {
535 /* Get the allocated range */
536 res = find_resource(dev, 0x44);
537
538 if (res->base == 0) {
539 printk(BIOS_WARNING, "Unable to allocate MMIO range to IOMMU\n");
540 }
541
542 /* Assign the range to hardware */
543 pci_write_config32(dev, 0x44, res->base & 0xffffc000);
544 pci_write_config32(dev, 0x48, 0x0);
545 }
546
547 /* Run standard resource set routine */
548 pci_dev_set_resources(dev);
549}
550
551void sr5650_iommu_enable_resources(device_t dev)
552{
553 detect_and_enable_iommu(dev);
554}
555
Zheng Bao98fcc092011-03-27 16:39:58 +0000556void sr5650_nb_pci_table(device_t nb_dev)
557{ /* NBPOR_InitPOR function. */
558 u8 temp8;
559 u16 temp16;
560 u32 temp32;
561
562 /* Program NB PCI table. */
563 temp16 = pci_read_config16(nb_dev, 0x04);
564 printk(BIOS_DEBUG, "NB_PCI_REG04 = %x.\n", temp16);
565 temp32 = pci_read_config32(nb_dev, 0x84);
566 printk(BIOS_DEBUG, "NB_PCI_REG84 = %x.\n", temp32);
567 //Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge
568 //Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation
569 pci_write_config8(nb_dev, 0x4c, 0x42);
570 temp8 = pci_read_config8(nb_dev, 0x4e);
571 temp8 |= 0x05; /* BAR1_ENABLE */
572 pci_write_config8(nb_dev, 0x4e, temp8);
573
574 temp32 = pci_read_config32(nb_dev, 0x4c);
575 printk(BIOS_DEBUG, "NB_PCI_REG4C = %x.\n", temp32);
576
577 /* disable GFX debug. */
578 temp8 = pci_read_config8(nb_dev, 0x8d);
579 temp8 &= ~(1<<1);
580 pci_write_config8(nb_dev, 0x8d, temp8);
581
efdesign9800c8c4a2011-07-20 12:37:58 -0600582 /* The system top memory in SR56X0. */
Zheng Bao98fcc092011-03-27 16:39:58 +0000583 sr5650_set_tom(nb_dev);
584
585 /* Program NB HTIU table. */
586 //set_htiu_enable_bits(nb_dev, 0x05, 1<<10 | 1<<9, 1<<10|1<<9);
587 set_htiu_enable_bits(nb_dev, 0x06, 1, 0x4203a202);
588 //set_htiu_enable_bits(nb_dev, 0x07, 1<<1 | 1<<2, 0x8001);
589 set_htiu_enable_bits(nb_dev, 0x15, 0, 1<<31 | 1<<30 | 1<<27);
590 set_htiu_enable_bits(nb_dev, 0x1c, 0, 0xfffe0000);
591 set_htiu_enable_bits(nb_dev, 0x0c, 0x3f, 1 | 1<<3);
592 set_htiu_enable_bits(nb_dev, 0x19, 0xfffff+(1<<31), 0x186a0+(1<<31));
593 set_htiu_enable_bits(nb_dev, 0x16, 0x3f<<10, 0x7<<10);
594 set_htiu_enable_bits(nb_dev, 0x23, 0, 1<<28);
595}
596
597/***********************************************
598* 0:00.0 NBCFG :
599* 0:00.1 CLK : bit 0 of nb_cfg 0x4c : 0 - disable, default
600* 0:01.0 P2P Internal:
601* 0:02.0 P2P : bit 2 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
602* 0:03.0 P2P : bit 3 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
603* 0:04.0 P2P : bit 4 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
604* 0:05.0 P2P : bit 5 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
605* 0:06.0 P2P : bit 6 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
606* 0:07.0 P2P : bit 7 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
607* 0:08.0 NB2SB : bit 6 of nbmiscind 0x00 : 0 - disable, default + 32 * 1
608* case 0 will be called twice, one is by cpu in hypertransport.c line458,
609* the other is by sr5650.
610***********************************************/
611void sr5650_enable(device_t dev)
612{
613 device_t nb_dev = 0, sb_dev = 0;
614 int dev_ind;
Timothy Pearson5a0efd22015-06-12 20:08:29 -0500615 struct southbridge_amd_sr5650_config *cfg;
Zheng Bao98fcc092011-03-27 16:39:58 +0000616
617 printk(BIOS_INFO, "sr5650_enable: dev=%p, VID_DID=0x%x\n", dev, get_vid_did(dev));
618 nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0));
619 if (!nb_dev) {
620 die("sr5650_enable: CAN NOT FIND SR5650 DEVICE, HALT!\n");
621 /* NOT REACHED */
622 }
Timothy Pearson5a0efd22015-06-12 20:08:29 -0500623 cfg = (struct southbridge_amd_sr5650_config *)nb_dev->chip_info;
Zheng Bao98fcc092011-03-27 16:39:58 +0000624
625 /* sb_dev (dev 8) is a bridge that links to southbridge. */
626 sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0));
627 if (!sb_dev) {
628 die("sr5650_enable: CAN NOT FIND SB bridge, HALT!\n");
629 /* NOT REACHED */
630 }
631
632 dev_ind = dev->path.pci.devfn >> 3;
633 switch (dev_ind) {
634 case 0: /* bus0, dev0, fun0; */
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500635 switch (dev->path.pci.devfn & 0x7) {
636 case 0:
637 printk(BIOS_INFO, "Bus-0, Dev-0, Fun-0.\n");
638 enable_pcie_bar3(nb_dev); /* PCIEMiscInit */
Zheng Bao98fcc092011-03-27 16:39:58 +0000639
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500640 config_gpp_core(nb_dev, sb_dev);
641 sr5650_gpp_sb_init(nb_dev, sb_dev, 8);
Zheng Bao98fcc092011-03-27 16:39:58 +0000642
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500643 sr5650_nb_pci_table(nb_dev);
644 break;
645 case 1:
646 printk(BIOS_INFO, "Bus-0, Dev-0, Fun-1.\n");
647 break;
648 case 2:
649 printk(BIOS_INFO, "Bus-0, Dev-0, Fun-2.\n");
650 break;
651 }
Zheng Bao98fcc092011-03-27 16:39:58 +0000652 break;
653
654 case 2: /* bus0, dev2,3 GPP1 */
655 case 3:
656 printk(BIOS_INFO, "Bus-0, Dev-2,3, Fun-0. enable=%d\n", dev->enabled);
657 set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind,
658 (dev->enabled ? 0 : 1) << dev_ind);
659 if (dev->enabled)
660 sr5650_gpp_sb_init(nb_dev, dev, dev_ind); /* Note, dev 2,3 are generic PCIe ports. */
661 break;
662 case 4: /* bus0, dev4-7, four GPP3a */
663 case 5:
664 case 6:
665 case 7:
666 enable_pcie_bar3(nb_dev); /* PCIEMiscInit */
667 printk(BIOS_INFO, "Bus-0, Dev-4,5,6,7, Fun-0. enable=%d\n",
668 dev->enabled);
669 set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind,
670 (dev->enabled ? 0 : 1) << dev_ind);
671 if (dev->enabled)
672 sr5650_gpp_sb_init(nb_dev, dev, dev_ind);
673 break;
674 case 8: /* bus0, dev8, SB */
675 printk(BIOS_INFO, "Bus-0, Dev-8, Fun-0. enable=%d\n", dev->enabled);
676 set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6,
677 (dev->enabled ? 1 : 0) << 6);
678 if (dev->enabled)
679 sr5650_gpp_sb_init(nb_dev, dev, dev_ind);
680 disable_pcie_bar3(nb_dev);
681 break;
682 case 9: /* bus 0, dev 9,10, GPP3a */
683 case 10:
684 printk(BIOS_INFO, "Bus-0, Dev-9, 10, Fun-0. enable=%d\n",
685 dev->enabled);
686 enable_pcie_bar3(nb_dev); /* PCIEMiscInit */
687 set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind),
688 (dev->enabled ? 0 : 1) << (7 + dev_ind));
689 if (dev->enabled)
690 sr5650_gpp_sb_init(nb_dev, dev, dev_ind);
Martin Roth55e31a92014-12-16 20:53:49 -0700691 /* Don't call disable_pcie_bar3(nb_dev) here, otherwise the screen will crash. */
Zheng Bao98fcc092011-03-27 16:39:58 +0000692 break;
693 case 11:
694 case 12: /* bus 0, dev 11,12, GPP2 */
695 printk(BIOS_INFO, "Bus-0, Dev-11,12, Fun-0. enable=%d\n", dev->enabled);
696 set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind),
697 (dev->enabled ? 0 : 1) << (7 + dev_ind));
698 if (dev->enabled)
699 sr5650_gpp_sb_init(nb_dev, dev, dev_ind);
700 break;
701 case 13: /* bus 0, dev 12, GPP3b */
702 set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind),
703 (dev->enabled ? 0 : 1) << (7 + dev_ind));
704 if (dev->enabled)
705 sr5650_gpp_sb_init(nb_dev, dev, dev_ind);
706 break;
707 default:
708 printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev));
709 }
efdesign9800c8c4a2011-07-20 12:37:58 -0600710
711 /* Lock HWInit Register after the last device was done */
712 if (dev_ind == 13) {
713 sr56x0_lock_hwinitreg();
Timothy Pearson5a0efd22015-06-12 20:08:29 -0500714 udelay(cfg->pcie_settling_time);
efdesign9800c8c4a2011-07-20 12:37:58 -0600715 }
Zheng Bao98fcc092011-03-27 16:39:58 +0000716}
717
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500718static void add_ivrs_device_entries(struct device *parent, struct device *dev, int depth, int linknum, int8_t *root_level, unsigned long *current, uint16_t *length)
719{
720 uint8_t *p;
721 struct device *sibling;
722 struct bus *link;
723
724 if (!root_level) {
725 root_level = malloc(sizeof(int8_t));
726 *root_level = -1;
727 }
728
729 if (dev->path.type == DEVICE_PATH_PCI) {
730 if ((dev->bus->secondary == 0x0) && (dev->path.pci.devfn == 0x0))
731 *root_level = depth;
732
733 if (*root_level != -1) {
734 if (depth >= *root_level) {
735 if (dev->enabled) {
736 if (depth == *root_level) {
737 if (dev->path.pci.devfn < (0x1 << 3)) {
738 /* SR5690 control device */
739 } else if ((dev->path.pci.devfn >= (0x1 << 3)) && (dev->path.pci.devfn < (0xe << 3))) {
740 /* SR5690 PCIe bridge device */
741 } else {
742 if (dev->path.pci.devfn == (0x14 << 3)) {
743 /* SMBUS controller */
744 p = (uint8_t *) *current;
745 p[0] = 0x2; /* Entry type */
746 p[1] = dev->path.pci.devfn; /* Device */
747 p[2] = dev->bus->secondary; /* Bus */
748 p[3] = 0x97; /* Data */
749 p[4] = 0x0; /* Padding */
750 p[5] = 0x0; /* Padding */
751 p[6] = 0x0; /* Padding */
752 p[7] = 0x0; /* Padding */
753 *length += 8;
754 *current += 8;
755 } else {
756 /* Other southbridge device */
757 p = (uint8_t *) *current;
758 p[0] = 0x2; /* Entry type */
759 p[1] = dev->path.pci.devfn; /* Device */
760 p[2] = dev->bus->secondary; /* Bus */
761 p[3] = 0x0; /* Data */
762 p[4] = 0x0; /* Padding */
763 p[5] = 0x0; /* Padding */
764 p[6] = 0x0; /* Padding */
765 p[7] = 0x0; /* Padding */
766 *length += 8;
767 *current += 8;
768 }
769 }
770 } else {
771 if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) {
772 /* Device behind bridge */
773 if (pci_find_capability(dev, PCI_CAP_ID_PCIE)) {
774 /* Device is PCIe */
775 p = (uint8_t *) *current;
776 p[0] = 0x2; /* Entry type */
777 p[1] = dev->path.pci.devfn; /* Device */
778 p[2] = dev->bus->secondary; /* Bus */
779 p[3] = 0x0; /* Data */
780 p[4] = 0x0; /* Padding */
781 p[5] = 0x0; /* Padding */
782 p[6] = 0x0; /* Padding */
783 p[7] = 0x0; /* Padding */
784 *length += 8;
785 *current += 8;
786 } else {
787 /* Device is legacy PCI or PCI-X */
788 p = (uint8_t *) *current;
789 p[0] = 0x42; /* Entry type */
790 p[1] = dev->path.pci.devfn; /* Device */
791 p[2] = dev->bus->secondary; /* Bus */
792 p[3] = 0x0; /* Data */
793 p[4] = 0x0; /* Reserved */
794 p[5] = parent->path.pci.devfn; /* Device */
795 p[6] = parent->bus->secondary; /* Bus */
796 p[7] = 0x0; /* Reserved */
797 *length += 8;
798 *current += 8;
799 }
800 }
801 }
802 }
803 }
804 }
805 }
806
807 for (link = dev->link_list; link; link = link->next)
808 for (sibling = link->children; sibling; sibling = sibling->sibling)
809 add_ivrs_device_entries(dev, sibling, depth + 1, depth, root_level, current, length);
810
811 free(root_level);
812}
813
Timothy Pearson1eaaa0e2015-08-14 15:20:42 -0500814unsigned long acpi_fill_mcfg(unsigned long current)
815{
816 struct resource *res;
817 resource_t mmconf_base = EXT_CONF_BASE_ADDRESS;
818
819 if (IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)) {
820 res = sr5650_retrieve_cpu_mmio_resource();
821 if (res)
822 mmconf_base = res->base;
823
824 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, mmconf_base, 0x0, 0x0, 0x1f);
825 }
826
827 return current;
828}
829
Timothy Pearson44e4a4e2015-08-11 17:49:06 -0500830static unsigned long acpi_fill_ivrs(acpi_ivrs_t* ivrs, unsigned long current)
831{
832 uint8_t *p;
833
834 device_t nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0));
835 if (!nb_dev) {
836 printk(BIOS_WARNING, "acpi_fill_ivrs: Unable to locate SR5650 device! IVRS table not generated...\n");
837 return (unsigned long)ivrs;
838 }
839
840 device_t iommu_dev = dev_find_slot(0, PCI_DEVFN(0, 2));
841 if (!iommu_dev) {
842 printk(BIOS_WARNING, "acpi_fill_ivrs: Unable to locate SR5650 IOMMU device! IVRS table not generated...\n");
843 return (unsigned long)ivrs;
844 }
845
846 ivrs->iv_info = 0x0;
847 ivrs->iv_info |= (0x40 << 15); /* Maximum supported virtual address size */
848 ivrs->iv_info |= (0x34 << 8); /* Maximum supported physical address size */
849
850 ivrs->ivhd.type = 0x10;
851 ivrs->ivhd.flags = 0x0e;
852 // if (get_nb_rev(nb_dev) != REV_SR5650_A11) {
853 ivrs->ivhd.flags |= 0x10; /* Enable ATS support on all revisions except A11 */
854 // }
855 ivrs->ivhd.length = sizeof(struct acpi_ivrs_ivhd);
856 ivrs->ivhd.device_id = 0x2 | (nb_dev->bus->secondary << 8); /* BDF <bus>:00.2 */
857 ivrs->ivhd.capability_offset = 0x40; /* Capability block 0x40 (type 0xf, "Secure device") */
858 ivrs->ivhd.iommu_base_low = pci_read_config32(iommu_dev, 0x44) & 0xffffc000;
859 ivrs->ivhd.iommu_base_high = pci_read_config32(iommu_dev, 0x48);
860 ivrs->ivhd.pci_segment_group = 0x0;
861 ivrs->ivhd.iommu_info = 0x0;
862 ivrs->ivhd.iommu_info |= (0x14 << 8);
863 ivrs->ivhd.efr = 0x0;
864
865 /* Describe HPET */
866 p = (uint8_t *)current;
867 p[0] = 0x48; /* Entry type */
868 p[1] = 0; /* Device */
869 p[2] = 0; /* Bus */
870 p[3] = 0xd7; /* Data */
871 p[4] = 0x0; /* HPET number */
872 p[5] = 0x14 << 3; /* HPET device */
873 p[6] = nb_dev->bus->secondary; /* HPET bus */
874 p[7] = 0x2; /* Variety */
875 ivrs->ivhd.length += 8;
876 current += 8;
877
878 /* Describe PCI devices */
879 add_ivrs_device_entries(NULL, all_devices, 0, -1, NULL, &current, &ivrs->ivhd.length);
880
881 /* Describe IOAPICs */
882 unsigned long prev_current = current;
883 current = acpi_fill_ivrs_ioapic(ivrs, current);
884 ivrs->ivhd.length += (current - prev_current);
885
886 return current;
887}
888
889unsigned long southbridge_write_acpi_tables(device_t device,
890 unsigned long current,
891 struct acpi_rsdp *rsdp)
892{
893 unsigned char iommu;
894
895 iommu = 1;
896 get_option(&iommu, "iommu");
897
898 if (iommu) {
899 acpi_ivrs_t *ivrs;
900
901 /* IVRS */
902 current = ALIGN(current, 8);
903 printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current);
904 ivrs = (acpi_ivrs_t *) current;
905 acpi_create_ivrs(ivrs, acpi_fill_ivrs);
906 current += ivrs->header.length;
907 acpi_add_table(rsdp, ivrs);
908 }
909
910 return current;
911}
912
913static struct pci_operations iommu_ops_pci = {
914 .set_subsystem = pci_dev_set_subsystem,
915};
916
917static struct device_operations iommu_ops = {
918 .read_resources = sr5650_iommu_read_resources,
919 .set_resources = sr5650_iommu_set_resources,
920 .enable_resources = sr5650_iommu_enable_resources,
921 .write_acpi_tables = southbridge_write_acpi_tables,
922 .init = 0,
923 .scan_bus = 0,
924 .ops_pci = &iommu_ops_pci,
925};
926
927static const struct pci_driver ht_driver_sr5690 __pci_driver = {
928 .ops = &iommu_ops,
929 .vendor = PCI_VENDOR_ID_ATI,
930 .device = PCI_DEVICE_ID_AMD_SR5650_IOMMU,
931};
932
Zheng Bao98fcc092011-03-27 16:39:58 +0000933struct chip_operations southbridge_amd_sr5650_ops = {
934 CHIP_NAME("ATI SR5650")
935 .enable_dev = sr5650_enable,
936};