uboot/board/pcippc2/i2c.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <config.h>
  25#include <common.h>
  26#include <asm/io.h>
  27
  28#include "hardware.h"
  29#include "i2c.h"
  30
  31static void             i2c_start       (void);
  32static void             i2c_stop        (void);
  33static int              i2c_write       (u8             data);
  34static void             i2c_read        (u8 *           data);
  35
  36static inline void      i2c_port_start  (void);
  37static inline void      i2c_clock       (unsigned int   val);
  38static inline void      i2c_data        (unsigned int   val);
  39static inline unsigned int
  40                        i2c_in          (void);
  41static inline void      i2c_write_bit   (unsigned int   val);
  42static inline unsigned int
  43                        i2c_read_bit    (void);
  44
  45static inline void      i2c_udelay      (unsigned int   time);
  46
  47int i2c_read_byte (
  48  u8 *                  data,
  49  u8                    dev,
  50  u8                    offset)
  51{
  52  int                   err = 0;
  53
  54  i2c_start();
  55
  56  err = ! i2c_write(dev);
  57
  58  if (! err)
  59  {
  60    err = ! i2c_write(offset);
  61  }
  62
  63  if (! err)
  64  {
  65    i2c_start();
  66  }
  67
  68  if (! err)
  69  {
  70    err = ! i2c_write(dev | 0x01);
  71  }
  72
  73  if (! err)
  74  {
  75    i2c_read(data);
  76  }
  77
  78  i2c_stop();
  79
  80  return ! err;
  81}
  82
  83static inline void i2c_udelay (
  84  unsigned int          time)
  85{
  86  int                   v;
  87
  88  asm volatile("mtdec %0" : : "r" (time * ((CONFIG_SYS_BUS_CLK / 4) / 1000000)));
  89
  90  do
  91  {
  92    asm volatile("isync; mfdec %0" : "=r" (v));
  93  } while (v >= 0);
  94}
  95
  96  /* Low-level hardware access
  97   */
  98
  99#define BIT_GPDATA              0x80000000
 100#define BIT_GPCLK               0x40000000
 101
 102static inline void i2c_port_start (void)
 103{
 104  out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~(BIT_GPCLK | BIT_GPDATA));
 105  out32(REG(CPC0, GPOUT), in32(REG(CPC0, GPOUT)) & ~(BIT_GPCLK | BIT_GPDATA));
 106  iobarrier_rw();
 107
 108  i2c_udelay(1);
 109}
 110
 111static inline void i2c_clock (
 112  unsigned int          val)
 113{
 114  if (val)
 115  {
 116    out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPCLK);
 117  }
 118  else
 119  {
 120    out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPCLK);
 121  }
 122
 123  iobarrier_rw();
 124
 125  i2c_udelay(1);
 126}
 127
 128static inline void i2c_data (
 129  unsigned int          val)
 130{
 131  if (val)
 132  {
 133    out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPDATA);
 134  }
 135  else
 136  {
 137    out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPDATA);
 138  }
 139
 140  iobarrier_rw();
 141
 142  i2c_udelay(1);
 143}
 144
 145static inline unsigned int i2c_in (void)
 146{
 147  unsigned int          val = ((in32(REG(CPC0, GPIN)) & BIT_GPDATA) != 0)?1:0;
 148
 149  iobarrier_rw();
 150
 151  return val;
 152}
 153
 154
 155  /* Protocol implementation
 156   */
 157
 158static inline void i2c_write_bit (
 159  unsigned int          val)
 160{
 161  i2c_data(val);
 162  i2c_udelay(10);
 163  i2c_clock(1);
 164  i2c_udelay(10);
 165  i2c_clock(0);
 166  i2c_udelay(10);
 167}
 168
 169static inline unsigned int i2c_read_bit (void)
 170{
 171  unsigned int          val;
 172
 173  i2c_data(1);
 174  i2c_udelay(10);
 175
 176  i2c_clock(1);
 177  i2c_udelay(10);
 178
 179  val = i2c_in();
 180
 181  i2c_clock(0);
 182  i2c_udelay(10);
 183
 184  return val;
 185}
 186
 187unsigned int i2c_reset (void)
 188{
 189  unsigned int          val;
 190  int i;
 191
 192  i2c_port_start();
 193
 194  i=0;
 195  do {
 196    i2c_udelay(10);
 197    i2c_clock(0);
 198    i2c_udelay(10);
 199    i2c_clock(1);
 200    i2c_udelay(10);
 201    val = i2c_in();
 202    i++;
 203  }  while ((i<9)&&(val==0));
 204  return (val);
 205}
 206
 207
 208static void i2c_start (void)
 209{
 210  i2c_data(1);
 211  i2c_clock(1);
 212  i2c_udelay(10);
 213  i2c_data(0);
 214  i2c_udelay(10);
 215  i2c_clock(0);
 216  i2c_udelay(10);
 217}
 218
 219static void i2c_stop (void)
 220{
 221  i2c_data(0);
 222  i2c_udelay(10);
 223  i2c_clock(1);
 224  i2c_udelay(10);
 225  i2c_data(1);
 226  i2c_udelay(10);
 227}
 228
 229static int i2c_write (
 230  u8                    data)
 231{
 232  unsigned int          i;
 233
 234  for (i = 0; i < 8; i++)
 235  {
 236    i2c_write_bit(data >> 7);
 237    data <<= 1;
 238  }
 239
 240  return i2c_read_bit() == 0;
 241}
 242
 243static void i2c_read (
 244  u8 *                  data)
 245{
 246  unsigned int          i;
 247  u8                    val = 0;
 248
 249  for (i = 0; i < 8; i++)
 250  {
 251    val <<= 1;
 252    val |= i2c_read_bit();
 253  }
 254
 255  *data = val;
 256  i2c_write_bit(1); /* NoAck */
 257}
 258