| /* |
| * This file is part of the coreboot project. |
| * |
| * Copyright (C) 2010 Advanced Micro Devices, Inc. |
| * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; version 2 of the License. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| /* Low swap bit vs bank size encoding (physical, not logical address bit) |
| * ;To calculate the number by hand, add the number of Bank address bits |
| * ;(2 or 3) to the number of column address bits, plus 3 (the logical |
| * ;page size), and subtract 8. |
| */ |
| static const u8 Tab_int_D[] = {6,7,7,8,8,8,8,8,9,9,8,9}; |
| |
| void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, |
| struct DCTStatStruc *pDCTstat, u8 dct) |
| { |
| u8 ChipSel, EnChipSels; |
| u32 AddrLoMask, AddrHiMask; |
| u32 AddrLoMaskN, AddrHiMaskN, MemSize = 0; |
| u8 DoIntlv, _CsIntCap; |
| u32 BitDelta, BankEncd = 0; |
| |
| u32 dev; |
| u32 reg; |
| u32 val; |
| u32 val_lo, val_hi; |
| |
| DoIntlv = mctGet_NVbits(NV_BankIntlv); |
| _CsIntCap = 0; |
| EnChipSels = 0; |
| |
| dev = pDCTstat->dev_dct; |
| |
| ChipSel = 0; /* Find out if current configuration is capable */ |
| while (DoIntlv && (ChipSel < MAX_CS_SUPPORTED)) { |
| reg = 0x40+(ChipSel<<2); /* Dram CS Base 0 */ |
| val = Get_NB32_DCT(dev, dct, reg); |
| if (val & (1<<CSEnable)) { |
| EnChipSels++; |
| reg = 0x60+((ChipSel>>1)<<2); /*Dram CS Mask 0 */ |
| val = Get_NB32_DCT(dev, dct, reg); |
| val >>= 19; |
| val &= 0x3ff; |
| val++; |
| if (EnChipSels == 1) |
| MemSize = val; |
| else |
| /*If mask sizes not same then skip */ |
| if (val != MemSize) |
| break; |
| reg = 0x80; /*Dram Bank Addressing */ |
| val = Get_NB32_DCT(dev, dct, reg); |
| val >>= (ChipSel>>1)<<2; |
| val &= 0x0f; |
| if (EnChipSels == 1) |
| BankEncd = val; |
| else |
| /*If number of Rows/Columns not equal, skip */ |
| if (val != BankEncd) |
| break; |
| } |
| ChipSel++; |
| } |
| if (ChipSel == MAX_CS_SUPPORTED) { |
| if ((EnChipSels == 2) || (EnChipSels == 4) || (EnChipSels == 8)) |
| _CsIntCap = 1; |
| } |
| |
| if (DoIntlv) { |
| if (!_CsIntCap) { |
| pDCTstat->ErrStatus |= 1<<SB_BkIntDis; |
| DoIntlv = 0; |
| } |
| } |
| |
| if (DoIntlv) { |
| val = Tab_int_D[BankEncd]; |
| if (pDCTstat->Status & (1<<SB_128bitmode)) |
| val++; |
| |
| AddrLoMask = (EnChipSels - 1) << val; |
| AddrLoMaskN = ~AddrLoMask; |
| |
| val = bsf(MemSize) + 19; |
| AddrHiMask = (EnChipSels -1) << val; |
| AddrHiMaskN = ~AddrHiMask; |
| |
| BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask); |
| |
| for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) { |
| reg = 0x40 + (ChipSel<<2); /* Dram CS Base 0 */ |
| val = Get_NB32_DCT(dev, dct, reg); |
| if (val & 3) { |
| val_lo = val & AddrLoMask; |
| val_hi = val & AddrHiMask; |
| val &= AddrLoMaskN; |
| val &= AddrHiMaskN; |
| val_lo <<= BitDelta; |
| val_hi >>= BitDelta; |
| val |= val_lo; |
| val |= val_hi; |
| Set_NB32_DCT(dev, dct, reg, val); |
| |
| if (ChipSel & 1) |
| continue; |
| |
| reg = 0x60 + ((ChipSel>>1)<<2); /* Dram CS Mask 0 */ |
| val = Get_NB32_DCT(dev, dct, reg); |
| val_lo = val & AddrLoMask; |
| val_hi = val & AddrHiMask; |
| val &= AddrLoMaskN; |
| val &= AddrHiMaskN; |
| val_lo <<= BitDelta; |
| val_hi >>= BitDelta; |
| val |= val_lo; |
| val |= val_hi; |
| Set_NB32_DCT(dev, dct, reg, val); |
| } |
| } |
| } /* DoIntlv */ |
| |
| /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ |
| |
| printk(BIOS_DEBUG, "InterleaveBanks_D: Status %x\n", pDCTstat->Status); |
| printk(BIOS_DEBUG, "InterleaveBanks_D: ErrStatus %x\n", pDCTstat->ErrStatus); |
| printk(BIOS_DEBUG, "InterleaveBanks_D: ErrCode %x\n", pDCTstat->ErrCode); |
| printk(BIOS_DEBUG, "InterleaveBanks_D: Done\n\n"); |
| } |