coreboot-v3/southbridge/nvidia/ck804/shared_smbus.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright 2004 Tyan Computer
   5 *  by yhlu@tyan.com
   6 *
   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; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  20 */
  21
  22#include <types.h>
  23#include <device/smbus.h>
  24#include <device/smbus_def.h>
  25#include <device/pci_ids.h>
  26#include <device/pci_ops.h>
  27#include <device/pci.h>
  28#include <device/device.h>
  29#include <console.h>
  30#include <io.h>
  31#include "ck804_smbus.h"
  32
  33static inline void smbus_delay(void)
  34{
  35        outb(0x80, 0x80);
  36}
  37
  38int smbus_wait_until_ready(unsigned smbus_io_base)
  39{
  40        unsigned long loops;
  41        loops = SMBUS_TIMEOUT;
  42        do {
  43                unsigned char val;
  44                smbus_delay();
  45                val = inb(smbus_io_base + SMBHSTSTAT);
  46                val &= 0x1f;
  47                if (val == 0)
  48                        return 0;
  49                outb(val, smbus_io_base + SMBHSTSTAT);
  50        } while (--loops);
  51        return -2;
  52}
  53
  54int smbus_wait_until_done(unsigned smbus_io_base)
  55{
  56        unsigned long loops;
  57        loops = SMBUS_TIMEOUT;
  58        do {
  59                unsigned char val;
  60                smbus_delay();
  61                val = inb(smbus_io_base + SMBHSTSTAT);
  62                if ((val & 0xff) != 0)
  63                        return 0;
  64        } while (--loops);
  65        return -3;
  66}
  67
  68int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
  69{
  70        unsigned char global_status_register, byte;
  71
  72        /* Set the device I'm talking to. */
  73        outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
  74        smbus_delay();
  75
  76        /* Set the command/address. */
  77        outb(0, smbus_io_base + SMBHSTCMD);
  78        smbus_delay();
  79
  80        /* Byte data recv */
  81        outb(0x05, smbus_io_base + SMBHSTPRTCL);
  82        smbus_delay();
  83
  84        /* Poll for transaction completion. */
  85        if (smbus_wait_until_done(smbus_io_base) < 0)
  86                return -3;
  87
  88        /* Lose check */
  89        global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
  90
  91        /* Read results of transaction. */
  92        byte = inb(smbus_io_base + SMBHSTDAT0);
  93
  94        /* Lose check, otherwise it should be 0. */
  95        if (global_status_register != 0x80)
  96                return -1;
  97
  98        return byte;
  99}
 100
 101int do_smbus_send_byte(unsigned smbus_io_base, unsigned device,
 102                              unsigned char val)
 103{
 104        unsigned global_status_register;
 105
 106        outb(val, smbus_io_base + SMBHSTDAT0);
 107        smbus_delay();
 108
 109        /* Set the device I'm talking to. */
 110        outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
 111        smbus_delay();
 112
 113        outb(0, smbus_io_base + SMBHSTCMD);
 114        smbus_delay();
 115
 116        /* Set up for a byte data write. */
 117        outb(0x04, smbus_io_base + SMBHSTPRTCL);
 118        smbus_delay();
 119
 120        /* Poll for transaction completion. */
 121        if (smbus_wait_until_done(smbus_io_base) < 0)
 122                return -3;
 123
 124        /* Lose check */
 125        global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
 126
 127        if (global_status_register != 0x80)
 128                return -1;
 129
 130        return 0;
 131}
 132
 133int do_smbus_read_byte(unsigned smbus_io_base, unsigned device,
 134                              unsigned address)
 135{
 136        unsigned char global_status_register, byte;
 137
 138        /* Set the device I'm talking to. */
 139        outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
 140        smbus_delay();
 141
 142        /* Set the command/address. */
 143        outb(address & 0xff, smbus_io_base + SMBHSTCMD);
 144        smbus_delay();
 145
 146        /* Byte data read */
 147        outb(0x07, smbus_io_base + SMBHSTPRTCL);
 148        smbus_delay();
 149
 150        /* Poll for transaction completion. */
 151        if (smbus_wait_until_done(smbus_io_base) < 0)
 152                return -3;
 153
 154        /* Lose check */
 155        global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
 156
 157        /* Read results of transaction. */
 158        byte = inb(smbus_io_base + SMBHSTDAT0);
 159
 160        /* Lose check, otherwise it should be 0. */
 161        if (global_status_register != 0x80)
 162                return -1;
 163
 164        return byte;
 165}
 166
 167int do_smbus_write_byte(unsigned smbus_io_base, unsigned device,
 168                               unsigned address, unsigned char val)
 169{
 170        unsigned global_status_register;
 171
 172        outb(val, smbus_io_base + SMBHSTDAT0);
 173        smbus_delay();
 174
 175        /* Set the device I'm talking to. */
 176        outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
 177        smbus_delay();
 178
 179        outb(address & 0xff, smbus_io_base + SMBHSTCMD);
 180        smbus_delay();
 181
 182        /* Set up for a byte data write. */
 183        outb(0x06, smbus_io_base + SMBHSTPRTCL);
 184        smbus_delay();
 185
 186        /* Poll for transaction completion. */
 187        if (smbus_wait_until_done(smbus_io_base) < 0)
 188                return -3;
 189
 190        /* Lose check */
 191        global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80;
 192
 193        if (global_status_register != 0x80)
 194                return -1;
 195
 196        return 0;
 197}
 198
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.