rs780: correct comment in switching_gpp_configurations()
[coreboot.git] / src / southbridge / amd / rs780 / pcie.c
1 /*
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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include <console/console.h>
21 #include <device/device.h>
22 #include <device/pci.h>
23 #include <device/pci_ids.h>
24 #include <device/pci_ops.h>
25 #include <delay.h>
26 #include "rs780.h"
27
28 /*------------------------------------------------
29 * Global variable
30 ------------------------------------------------*/
31 PCIE_CFG AtiPcieCfg = {
32         PCIE_ENABLE_STATIC_DEV_REMAP,   /* Config */
33         0,                      /* ResetReleaseDelay */
34         0,                      /* Gfx0Width */
35         0,                      /* Gfx1Width */
36         0,                      /* GfxPayload */
37         0,                      /* GppPayload */
38         0,                      /* PortDetect, filled by GppSbInit */
39         0,                      /* PortHp */
40         0,                      /* DbgConfig */
41         0,                      /* DbgConfig2 */
42         0,                      /* GfxLx */
43         0,                      /* GppLx */
44         0,                      /* NBSBLx */
45         0,                      /* PortSlotInit */
46         0,                      /* Gfx0Pwr */
47         0,                      /* Gfx1Pwr */
48         0                       /* GppPwr */
49 };
50
51 static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port);
52 static void ValidatePortEn(device_t nb_dev);
53
54 static void ValidatePortEn(device_t nb_dev)
55 {
56 }
57
58 /*****************************************************************
59 * Compliant with CIM_33's PCIEPowerOffGppPorts
60 * Power off unused GPP lines
61 *****************************************************************/
62 static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port)
63 {
64         u32 reg;
65         u16 state_save;
66         struct southbridge_amd_rs780_config *cfg =
67             (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
68         u8 state = cfg->port_enable;
69
70         if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS))
71                 state &= AtiPcieCfg.PortDetect;
72         state = ~state;
73         state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7);
74         state_save = state << 17;
75         state &= ~(AtiPcieCfg.PortHp);
76         reg = nbmisc_read_index(nb_dev, 0x0c);
77         reg |= state;
78         nbmisc_write_index(nb_dev, 0x0c, reg);
79
80         reg = nbmisc_read_index(nb_dev, 0x08);
81         reg |= state_save;
82         nbmisc_write_index(nb_dev, 0x08, reg);
83
84         if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES)
85             && !(AtiPcieCfg.
86                  Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS +
87                            PCIE_GFX_COMPLIANCE))) {
88         }
89
90         /* step 3 Power Down Control for Southbridge */
91         if (port != 8)
92                 return;
93
94         reg = nbpcie_p_read_index(dev, 0xa2);
95
96         switch ((reg >> 4) & 0x7) {     /* get bit 4-6, LC_LINK_WIDTH_RD */
97         case 1:
98                 set_pcie_enable_bits(nb_dev, 0x65 | PCIE_CORE_INDEX_GPPSB,
99                                      0x0f0f, 0x0e0e);
100                 break;
101         case 2:
102                 set_pcie_enable_bits(nb_dev, 0x65 | PCIE_CORE_INDEX_GPPSB,
103                                      0x0f0f, 0x0c0c);
104                 break;
105         default:
106                 break;
107         }
108 }
109
110 /**********************************************************************
111 **********************************************************************/
112 static void switching_gppsb_configurations(device_t nb_dev, device_t sb_dev)
113 {
114         u32 reg;
115         struct southbridge_amd_rs780_config *cfg =
116             (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
117
118         /* 5.5.7.1-3 enables GPP reconfiguration */
119         reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7);
120         reg |=
121             (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG +
122              RECONFIG_GPPSB_ATOMIC_RESET);
123         nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg);
124
125         /* 5.5.7.4a. De-asserts STRAP_BIF_all_valid for PCIE-GPPSB core */
126         reg = nbmisc_read_index(nb_dev, 0x66);
127         reg |= 1 << 31;
128         nbmisc_write_index(nb_dev, 0x66, reg);
129         /* 5.5.7.4b. sets desired GPPSB configurations, bit4-7 */
130         reg = nbmisc_read_index(nb_dev, 0x67);
131         reg &= 0xFFFFff0f;              /* clean */
132         reg |= cfg->gppsb_configuration << 4;
133         nbmisc_write_index(nb_dev, 0x67, reg);
134
135 #if 1
136         /* NOTE:
137          * In CIMx 4.5.0 and RPR, 4c is done before 5 & 6. But in this way,
138          * a x4 device in port B (dev 4) of Configuration B can only be detected
139          * as x1, instead of x4. When the port B is being trained, the
140          * LC_CURRENT_STATE is 6 and the LC_LINK_WIDTH_RD is 1. We have
141          * to set the PCIEIND:0x65 as 0xE0E0 and reset the slot. Then the card
142          * seems to work in x1 mode.
143          * In the 2nd way below, we do the 5 & 6 before 4c. it conforms the
144          * CIMx 4.3.0. It conflicts with RPR. But based on the test result I've
145          * made so far, I haven't found any mistake.
146          */
147         /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */
148         reg = nbmisc_read_index(nb_dev, 0x66);
149         reg &= ~(1 << 31);
150         nbmisc_write_index(nb_dev, 0x66, reg);
151
152         /* 5.5.7.5-6. read bit14 and write back its inverst value */
153         reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7);
154         reg ^= RECONFIG_GPPSB_GPPSB;
155         nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg);
156 #else
157         /* 5.5.7.5-6. read bit14 and write back its inverst value */
158         reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7);
159         reg ^= RECONFIG_GPPSB_GPPSB;
160         nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg);
161
162         /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */
163         reg = nbmisc_read_index(nb_dev, 0x66);
164         reg &= ~(1 << 31);
165         nbmisc_write_index(nb_dev, 0x66, reg);
166 #endif
167         /* 5.5.7.7. delay 1ms */
168         mdelay(1);
169
170         /* 5.5.7.8. waits until SB has trained to L0, poll for bit0-5 = 0x10 */
171         do {
172                 reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0);
173                 reg &= 0x3f;    /* remain LSB [5:0] bits */
174         } while (LC_STATE_RECONFIG_GPPSB != reg);
175
176         /* 5.5.7.9.ensures that virtual channel negotiation is completed. poll for bit1 = 0 */
177         do {
178                 reg =
179                     pci_ext_read_config32(nb_dev, sb_dev,
180                                           PCIE_VC0_RESOURCE_STATUS);
181         } while (reg & VC_NEGOTIATION_PENDING);
182 }
183
184 static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev)
185 {
186         u32 reg;
187         struct southbridge_amd_rs780_config *cfg =
188             (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
189
190         /* 5.6.2.1. De-asserts STRAP_BIF_all_valid for PCIE-GPP core */
191         reg = nbmisc_read_index(nb_dev, 0x22);
192         reg |= 1 << 14;
193         nbmisc_write_index(nb_dev, 0x22, reg);
194         /* 5.6.2.2. sets desired GPP configurations, bit7-10 */
195         reg = nbmisc_read_index(nb_dev, 0x2D);
196         reg &= ~(0xF << 7);             /* clean */
197         reg |= cfg->gpp_configuration << 7;
198         nbmisc_write_index(nb_dev, 0x2D, reg);
199         /* 5.6.2.3. Asserts STRAP_BIF_all_valid for PCIE-GPP core */
200         reg = nbmisc_read_index(nb_dev, 0x22);
201         reg &= ~(1 << 14);
202         nbmisc_write_index(nb_dev, 0x22, reg);
203 }
204
205 /*****************************************************************
206 * The rs780 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration
207 * Space to a 256MB range within the first 4GB of addressable memory.
208 *****************************************************************/
209 void enable_pcie_bar3(device_t nb_dev)
210 {
211         printk(BIOS_DEBUG, "enable_pcie_bar3()\n");
212         set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30);  /* Enables writes to the BAR3 register. */
213         set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16);
214
215         pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS);        /* PCIEMiscInit */
216         pci_write_config32(nb_dev, 0x20, 0x00000000);
217         set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28);   /* PCIEMiscInit */
218         ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
219 }
220
221 /*****************************************************************
222 * We should disable bar3 when we want to exit rs780_enable, because bar3 will be
223 * remapped in set_resource later.
224 *****************************************************************/
225 void disable_pcie_bar3(device_t nb_dev)
226 {
227         printk(BIOS_DEBUG, "disable_pcie_bar3()\n");
228         pci_write_config32(nb_dev, 0x1C, 0);    /* clear BAR3 address */
229         set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30);  /* Disable writes to the BAR3. */
230         set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0); /* disable bar3 decode */
231         ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
232 }
233
234 /*****************************************
235 * Compliant with CIM_33's PCIEGPPInit
236 * nb_dev:
237 *       root bridge struct
238 * dev:
239 *       p2p bridge struct
240 * port:
241 *       p2p bridge number, 4-10
242 *****************************************/
243 void rs780_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
244 {
245         u32 gfx_gpp_sb_sel;
246         struct southbridge_amd_rs780_config *cfg =
247             (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
248         printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%x, dev=0x%x, port=0x%x\n", nb_dev->path.pci.devfn, dev->path.pci.devfn, port);
249
250         gfx_gpp_sb_sel = port >= 4 && port <= 8 ?
251                                 PCIE_CORE_INDEX_GPPSB :         /* 4,5,6,7,8 */
252                                 PCIE_CORE_INDEX_GPP;            /* 9,10 */
253         /* init GPP core */
254         /* 5.10.8.3. Disable slave ordering logic */
255         set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 8,
256                              1 << 8);
257         /* 5.10.8.7. PCIE initialization 5.10.2: rpr 2.12*/
258         set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0);    /* no description in datasheet. */
259
260         /* init GPPSB port. rpr 5.10.8 */
261         /* 5.10.8.1-5.10.8.2. Sets RCB timeout to be 100ms/4=25ms by setting bits[18:16] to 3 h4
262          * and shortens the enumeration timer by setting bit[19] to 1
263          */
264         set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0x4 << 16 | 1 << 19);
265         /* 5.10.8.4. Sets DMA payload size to 64 bytes. */
266         set_pcie_enable_bits(nb_dev, 0x10 | gfx_gpp_sb_sel, 7 << 10, 4 << 10);
267         /* 5.10.8.6. Disable RC ordering logic */
268         set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 9, 1 << 9);
269         /* 5.10.8.7. Ignores DLLs druing L1 */
270         set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0);
271         /* 5.10.8.8. Prevents LCto go from L0 to Rcv_L0s if L1 is armed. */
272         set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
273         /* 5.10.8.9. Sets timer in Config state from 20us to 1us.
274          * 5.10.8.10. De-asserts RX_EN in L0s
275          * 5.10.8.11. Enables de-assertion of PG2RX_CR_EN to lock clock recovery parameter when .. */
276         set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 <<23 | 1 << 19 | 1 << 28);
277         /* 5.10.8.12. Turns off offset calibration */
278         /* 5.10.8.13. Enables Rx  Clock gating in CDR */
279         if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB)
280                 set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 14 | 1 << 26, 1 << 14 | 1 << 26); /* 4,5,6,7 */
281         else
282                 set_nbmisc_enable_bits(nb_dev, 0x24, 1 << 29 | 1 << 28, 1 << 29 | 1 << 28); /* 9,10 */
283         /* 5.10.8.14. Sets number of TX Clocks to drain TX Pipe to 3 */
284         set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 0x3 << 4);
285         /* 5.10.8.15. empty */
286         /* 5.10.8.16. P_ELEC_IDLE_MODE */
287         set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 0x3 << 14, 0x2 << 14);
288         /* 5.10.8.17. LC_BLOCK_EL_IDLE_IN_L0 */
289         set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20);
290         /* 5.10.8.18. LC_DONT_GO_TO_L0S_IFL1_ARMED */
291         set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
292         /* 5.10.8.19. RXP_REALIGN_ON_EACH_TSX_OR_SKP */
293         set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 1 << 28, 0 << 28);
294         /* 5.10.8.20. Bypass lane de-skew logic if in x1 */
295         set_pcie_enable_bits(nb_dev, 0xC2 | gfx_gpp_sb_sel, 1 << 14, 1 << 14);
296         /* 5.10.8.21. sets electrical idle threshold. */
297         if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB)
298                 set_nbmisc_enable_bits(nb_dev, 0x6A, 3 << 22, 2 << 22);
299         else
300                 set_nbmisc_enable_bits(nb_dev, 0x24, 3 << 16, 2 << 16);
301
302         /* 5.10.8.22. Disable GEN2 */
303         /* TODO: should be 2 seperated cases. */
304         set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 31, 0 << 31);
305         set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 5, 0 << 5);
306         set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 31, 0 << 31);
307         set_nbmisc_enable_bits(nb_dev, 0x37, 7 << 5, 0 << 5);
308         /* 5.10.8.23. Disables GEN2 capability of the device. RPR says enable? No! */
309         set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0);
310         /* 5.10.8.24. Disable advertising upconfigure support. */
311         set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13);
312         /* 5.10.8.25-26. STRAP_BIF_DSN_EN */
313         if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB)
314                 set_nbmisc_enable_bits(nb_dev, 0x68, 1 << 19, 0 << 19);
315         else
316                 set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 3, 0 << 3);
317         /* 5.10.8.27-28. */
318         set_pcie_enable_bits(nb_dev, 0xC1 | gfx_gpp_sb_sel, 1 << 0 | 1 << 2, 1 << 0 | 0 << 2);
319         /* 5.10.8.29. Uses the bif_core de-emphasis strength by default. */
320         if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) {
321                 set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 10, 1 << 10);
322                 set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 29, 1 << 29);
323         }
324         else {
325                 set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 30, 1 << 30);
326         }
327         /* 5.10.8.30. Set TX arbitration algorithm to round robin. */
328         set_pcie_enable_bits(nb_dev, 0x1C | gfx_gpp_sb_sel,
329                              1 << 0 | 0x1F << 1 | 0x1F << 6,
330                              1 << 0 | 0x04 << 1 | 0x04 << 6);
331
332         /* check compliance rpr step 2.1*/
333         if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) {
334                 u32 tmp;
335                 tmp = nbmisc_read_index(nb_dev, 0x67);
336                 tmp |= 1 << 3;
337                 nbmisc_write_index(nb_dev, 0x67, tmp);
338         }
339
340         /* step 5: dynamic slave CPL buffer allocation. Disable it, otherwise linux hangs. Why? */
341         /* set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 11, 1 << 11); */
342
343         /* step 5a: Training for GPP devices */
344         /* init GPP */
345         switch (port) {
346         case 4:         /* GPP */
347         case 5:
348         case 6:
349         case 7:
350         case 9:
351         case 10:
352                 /* 5.10.8.5. Blocks DMA traffic during C3 state */
353                 set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0);
354                 /* Enabels TLP flushing */
355                 set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19);
356
357                 /* check port enable */
358                 if (cfg->port_enable & (1 << port)) {
359                         PcieReleasePortTraining(nb_dev, dev, port);
360                         if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) {
361                                 u8 res = PcieTrainPort(nb_dev, dev, port);
362                                 printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res);
363                                 if (res) {
364                                         AtiPcieCfg.PortDetect |= 1 << port;
365                                 }
366                         }
367                 }
368                 break;
369         case 8:         /* SB */
370                 break;
371         }
372         PciePowerOffGppPorts(nb_dev, dev, port);
373 }
374
375 /*****************************************
376 * Compliant with CIM_33's PCIEConfigureGPPCore
377 *****************************************/
378 void config_gpp_core(device_t nb_dev, device_t sb_dev)
379 {
380         u32 reg;
381         struct southbridge_amd_rs780_config *cfg =
382             (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
383
384         reg = nbmisc_read_index(nb_dev, 0x20);
385         if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP)
386                 reg &= 0xfffffffd;      /* set bit1 = 0 */
387         else
388                 reg |= 0x2;     /* set bit1 = 1 */
389         nbmisc_write_index(nb_dev, 0x20, reg);
390
391         reg = nbmisc_read_index(nb_dev, 0x67);  /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */
392         if (cfg->gppsb_configuration != ((reg >> 4) & 0xf))
393                 switching_gppsb_configurations(nb_dev, sb_dev);
394         reg = nbmisc_read_index(nb_dev, 0x2D);  /* get STRAP_BIF_LINK_CONFIG_GPP at bit 7-10 */
395         if (cfg->gpp_configuration != ((reg >> 7) & 0xf))
396                 switching_gpp_configurations(nb_dev, sb_dev);
397         ValidatePortEn(nb_dev);
398 }
399
400 /**
401  * Hide unused Gpp port
402  */
403 void pcie_hide_unused_ports(device_t nb_dev)
404 {
405         u16 hide = 0x6FC; /* skip port 0, 1, 8 */
406
407         hide &= ~(AtiPcieCfg.PortDetect | AtiPcieCfg.PortHp);
408         printk(BIOS_INFO, "rs780 unused GPP ports bitmap=0x%03x, force disabled\n", hide);
409         set_nbmisc_enable_bits(nb_dev, 0x0C, 0xFC, (hide & 0xFC)); /* bridge 2-7 */
410         set_nbmisc_enable_bits(nb_dev, 0x0C, 0x30000, ((hide >> 9) & 0x3) << 16); /* bridge 9-a */
411 }