coreboot-v3/southbridge/amd/rs690/cmn.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2008 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 <types.h>
  21#include <lib.h>
  22#include <console.h>
  23#include <device/pci.h>
  24#include <msr.h>
  25#include <legacy.h>
  26#include <device/pci_ids.h>
  27#include <statictree.h>
  28#include <config.h>
  29#include "rs690.h"
  30
  31static u32 nb_read_index(struct device * dev, u32 index_reg, u32 index)
  32{
  33        pci_write_config32(dev, index_reg, index);
  34        return pci_read_config32(dev, index_reg + 0x4);
  35}
  36
  37static void nb_write_index(struct device * dev, u32 index_reg, u32 index, u32 data)
  38{
  39
  40        pci_write_config32(dev, index_reg, index);
  41        pci_write_config32(dev, index_reg + 0x4, data);
  42
  43}
  44
  45/* extension registers */
  46u32 pci_ext_read_config32(struct device * nb_dev, struct device * dev, u32 reg)
  47{
  48        /*get BAR3 base address for nbcfg0x1c */
  49        u32 addr = pci_read_config32(nb_dev, PCI_BASE_ADDRESS_3);
  50        printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary,
  51                     dev->path.pci.devfn);
  52        addr |= dev->bus->secondary << 20 |     /* bus num */
  53            dev->path.pci.devfn << 12 | reg;
  54        return *((u32 *) addr);
  55}
  56
  57void pci_ext_write_config32(struct device * nb_dev, struct device * dev, u32 reg_pos, u32 mask, u32 val)
  58{
  59        u32 reg_old, reg;
  60
  61        /*get BAR3 base address for nbcfg0x1c */
  62        u32 addr = pci_read_config32(nb_dev, PCI_BASE_ADDRESS_3);
  63        printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary,
  64                     dev->path.pci.devfn);
  65        addr |= dev->bus->secondary << 20 |     /* bus num */
  66            dev->path.pci.devfn << 12 | reg_pos;
  67
  68        reg = reg_old = *((u32 *) addr);
  69        reg &= ~mask;
  70        reg |= val;
  71        if (reg != reg_old) {
  72                *((u32 *) addr) = val;
  73        }
  74}
  75
  76u32 nbmisc_read_index(struct device * nb_dev, u32 index)
  77{
  78        return nb_read_index((nb_dev), NBMISC_INDEX, (index));
  79}
  80
  81void nbmisc_write_index(struct device * nb_dev, u32 index, u32 data)
  82{
  83        nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data));
  84}
  85
  86u32 nbpcie_p_read_index(struct device * dev, u32 index)
  87{
  88        return nb_read_index((dev), NBPCIE_INDEX, (index));
  89}
  90
  91void nbpcie_p_write_index(struct device * dev, u32 index, u32 data)
  92{
  93        nb_write_index((dev), NBPCIE_INDEX, (index), (data));
  94}
  95
  96u32 nbpcie_ind_read_index(struct device * nb_dev, u32 index)
  97{
  98        return nb_read_index((nb_dev), NBPCIE_INDEX, (index));
  99}
 100
 101void nbpcie_ind_write_index(struct device * nb_dev, u32 index, u32 data)
 102{
 103        nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data));
 104}
 105
 106u32 htiu_read_index(struct device * nb_dev, u32 index)
 107{
 108        return nb_read_index((nb_dev), NBHTIU_INDEX, (index));
 109}
 110
 111void htiu_write_index(struct device * nb_dev, u32 index, u32 data)
 112{
 113        nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data));
 114}
 115
 116u32 nbmc_read_index(struct device * nb_dev, u32 index)
 117{
 118        return nb_read_index((nb_dev), NBMC_INDEX, (index));
 119}
 120
 121void nbmc_write_index(struct device * nb_dev, u32 index, u32 data)
 122{
 123        nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data));
 124}
 125
 126void set_nbcfg_enable_bits(struct device * nb_dev, u32 reg_pos, u32 mask, u32 val)
 127{
 128        u32 reg_old, reg;
 129        reg = reg_old = pci_read_config32(nb_dev, reg_pos);
 130        reg &= ~mask;
 131        reg |= val;
 132        if (reg != reg_old) {
 133                pci_write_config32(nb_dev, reg_pos, reg);
 134        }
 135}
 136
 137void set_nbcfg_enable_bits_8(struct device * nb_dev, u32 reg_pos, u8 mask, u8 val)
 138{
 139        u8 reg_old, reg;
 140        reg = reg_old = pci_read_config8(nb_dev, reg_pos);
 141        reg &= ~mask;
 142        reg |= val;
 143        if (reg != reg_old) {
 144                pci_write_config8(nb_dev, reg_pos, reg);
 145        }
 146}
 147
 148void set_nbmc_enable_bits(struct device * nb_dev, u32 reg_pos, u32 mask, u32 val)
 149{
 150        u32 reg_old, reg;
 151        reg = reg_old = nbmc_read_index(nb_dev, reg_pos);
 152        reg &= ~mask;
 153        reg |= val;
 154        if (reg != reg_old) {
 155                nbmc_write_index(nb_dev, reg_pos, reg);
 156        }
 157}
 158
 159void set_htiu_enable_bits(struct device * nb_dev, u32 reg_pos, u32 mask, u32 val)
 160{
 161        u32 reg_old, reg;
 162        reg = reg_old = htiu_read_index(nb_dev, reg_pos);
 163        reg &= ~mask;
 164        reg |= val;
 165        if (reg != reg_old) {
 166                htiu_write_index(nb_dev, reg_pos, reg);
 167        }
 168}
 169
 170void set_nbmisc_enable_bits(struct device * nb_dev, u32 reg_pos, u32 mask, u32 val)
 171{
 172        u32 reg_old, reg;
 173        reg = reg_old = nbmisc_read_index(nb_dev, reg_pos);
 174        reg &= ~mask;
 175        reg |= val;
 176        if (reg != reg_old) {
 177                nbmisc_write_index(nb_dev, reg_pos, reg);
 178        }
 179}
 180
 181void set_pcie_enable_bits(struct device * dev, u32 reg_pos, u32 mask, u32 val)
 182{
 183        u32 reg_old, reg;
 184        reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos);
 185        reg &= ~mask;
 186        reg |= val;
 187        if (reg != reg_old) {
 188                nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg);
 189        }
 190}
 191
 192/***********************************************************
 193* To access bar3 we need to program PCI MMIO 7 in K8.
 194* in_out:
 195*       1: enable/enter k8 temp mmio base
 196*       0: disable/restore
 197***********************************************************/
 198void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add)
 199{
 200        /* K8 Function1 is address map */
 201        struct device * k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
 202
 203        if (in_out) {
 204                pci_write_config32(k8_f1, 0xbc,
 205                                   (((pcie_base_add + 0x10000000 -
 206                                     1) >> 8) & 0xffffff00) | 0x8);
 207                pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3);
 208                pci_write_config32(k8_f1, 0xb4,
 209                                   ((mmio_base_add + 0x10000000 -
 210                                     1) >> 8) & 0xffffff00);
 211                pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3);
 212        } else {
 213                pci_write_config32(k8_f1, 0xb8, 0);
 214                pci_write_config32(k8_f1, 0xbc, 0);
 215                pci_write_config32(k8_f1, 0xb0, 0);
 216                pci_write_config32(k8_f1, 0xb4, 0);
 217        }
 218}
 219
 220void PcieReleasePortTraining(struct device * nb_dev, struct device * dev, u32 port)
 221{
 222        switch (port) {
 223        case 2:         /* GFX, bit4-5 */
 224        case 3:
 225                set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG,
 226                                       1 << (port + 2), 0 << (port + 2));
 227                break;
 228        case 4:         /* GPP, bit20-24 */
 229        case 5:
 230        case 6:
 231        case 7:
 232                set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG,
 233                                       1 << (port + 17), 0 << (port + 17));
 234                break;
 235        }
 236}
 237
 238/********************************************************************************************************
 239* Output:
 240*       0: no device is present.
 241*       1: device is present and is trained.
 242********************************************************************************************************/
 243u8 PcieTrainPort(struct device * nb_dev, struct device * dev, u32 port)
 244{
 245        u16 count = 5000;
 246        u32 lc_state, reg;
 247        u8 current, res = 0;
 248
 249        while (count--) {
 250                mdelay(40);
 251                udelay(200);
 252                lc_state = nbpcie_p_read_index(dev, 0xa5);      /* lc_state */
 253                printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n",
 254                             port, lc_state);
 255                current = lc_state & 0x3f;      /* get LC_CURRENT_STATE, bit0-5 */
 256
 257                switch (current) {
 258                case 0x00:      /* 0x00-0x04 means no device is present */
 259                case 0x01:
 260                case 0x02:
 261                case 0x03:
 262                case 0x04:
 263                        res = 0;
 264                        count = 0;
 265                        break;
 266                case 0x07:      /* device is in compliance state (training sequence is doen). Move to train the next device */
 267                        res = 1;        /* TODO: CIM sets it to 0 */
 268                        count = 0;
 269                        break;
 270                case 0x10:
 271                        reg =
 272                            pci_ext_read_config32(nb_dev, dev,
 273                                                  PCIE_VC0_RESOURCE_STATUS);
 274                        printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg);
 275                        /* check bit1 */
 276                        if (reg & VC_NEGOTIATION_PENDING) {     /* bit1=1 means the link needs to be re-trained. */
 277                                /* set bit8=1, bit0-2=bit4-6 */
 278                                u32 tmp;
 279                                reg =
 280                                    nbpcie_p_read_index(dev,
 281                                                        PCIE_LC_LINK_WIDTH);
 282                                tmp = (reg >> 4) && 0x3;        /* get bit4-6 */
 283                                reg &= 0xfff8;  /* clear bit0-2 */
 284                                reg += tmp;     /* merge */
 285                                reg |= 1 << 8;
 286                                count++;        /* CIM said "keep in loop"?  */
 287                        } else {
 288                                res = 1;
 289                                count = 0;
 290                        }
 291                        break;
 292                default:        /* reset pcie */
 293                        res = 0;
 294                        count = 0;      /* break loop */
 295                        break;
 296                }
 297        }
 298        return res;
 299}
 300
 301/*
 302* Compliant with CIM_33's ATINB_SetToms.
 303* Set Top Of Memory below and above 4G.
 304*/
 305void rs690_set_tom(struct device * nb_dev)
 306{
 307        extern unsigned long uma_memory_start;
 308        /* set TOM */
 309        pci_write_config32(nb_dev, 0x90, uma_memory_start);
 310        nbmc_write_index(nb_dev, 0x1e, uma_memory_start);
 311}
 312
 313
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.