uboot/board/eltec/elppc/mpc107_i2c.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002 ELTEC Elektronik AG
   3 * Frank Gottschling <fgottschling@eltec.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/* includes */
  25#include <common.h>
  26#include "srom.h"
  27
  28/* locals */
  29static unsigned long mpc107_eumb_addr = 0;
  30
  31/*----------------------------------------------------------------------------*/
  32
  33/*
  34 * calculate checksum for ELTEC revision srom
  35 */
  36unsigned long el_srom_checksum (ptr, size)
  37register unsigned char *ptr;
  38unsigned long size;
  39{
  40    u_long f, accu = 0;
  41    u_int  i;
  42    u_char byte;
  43
  44    for (; size; size--)
  45    {
  46        byte = *ptr++;
  47        for (i = 8; i; i--)
  48        {
  49            f =  ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
  50            accu >>= 1; accu ^= f;
  51            byte >>= 1;
  52        }
  53    }
  54    return(accu);
  55}
  56
  57/*----------------------------------------------------------------------------*/
  58
  59static int mpc107_i2c_wait ( unsigned long timeout )
  60{
  61    unsigned long x;
  62
  63    while (((x = in32r(MPC107_I2CSR)) & 0x82) != 0x82)
  64    {
  65        if (!timeout--)
  66            return -1;
  67    }
  68
  69    if (x & 0x10)
  70    {
  71        return -1;
  72    }
  73    out32r(MPC107_I2CSR, 0);
  74
  75    return 0;
  76}
  77
  78/*----------------------------------------------------------------------------*/
  79
  80static int mpc107_i2c_wait_idle ( unsigned long timeout )
  81{
  82    while (in32r(MPC107_I2CSR) & 0x20)
  83    {
  84        if (!timeout--)
  85            return -1;
  86    }
  87    return 0;
  88}
  89
  90
  91/*----------------------------------------------------------------------------*/
  92
  93int mpc107_i2c_read_byte (
  94    unsigned char device,
  95    unsigned char block,
  96    unsigned char offset )
  97{
  98    unsigned long timeout = MPC107_I2C_TIMEOUT;
  99    int data;
 100
 101    if (!mpc107_eumb_addr)
 102        return -6;
 103
 104    mpc107_i2c_wait_idle (timeout);
 105
 106    /* Start with MEN */
 107    out32r(MPC107_I2CCR, 0x80);
 108
 109    /* Start as master */
 110    out32r(MPC107_I2CCR, 0xB0);
 111    out32r(MPC107_I2CDR, (0xA0 | device | block));
 112
 113    if (mpc107_i2c_wait(timeout) < 0)
 114    {
 115        printf("mpc107_i2c_read Error 1\n");
 116        return -2;
 117    }
 118
 119    if (in32r(MPC107_I2CSR)&0x1)
 120    {
 121        /* Generate STOP condition; device busy or not existing */
 122        out32r(MPC107_I2CCR, 0x80);
 123        return -1;
 124    }
 125
 126    /* Data address */
 127    out32r(MPC107_I2CDR, offset);
 128
 129    if (mpc107_i2c_wait(timeout) < 0)
 130    {
 131        printf("mpc107_i2c_read Error 2\n");
 132        return -3;
 133    }
 134
 135    /* Switch to read - restart */
 136    out32r(MPC107_I2CCR, 0xB4);
 137    out32r(MPC107_I2CDR, (0xA1 | device | block));
 138
 139    if (mpc107_i2c_wait(timeout) < 0)
 140    {
 141        printf("mpc107_i2c_read Error 3\n");
 142        return -4;
 143    }
 144
 145    out32r(MPC107_I2CCR, 0xA8); /* no ACK */
 146    in32r(MPC107_I2CDR);
 147
 148    if (mpc107_i2c_wait(timeout) < 0)
 149    {
 150        printf("mpc107_i2c_read Error 4\n");
 151        return -5;
 152    }
 153    /* Generate STOP condition */
 154    out32r(MPC107_I2CCR, 0x88);
 155
 156    /* read */
 157    data = in32r(MPC107_I2CDR);
 158
 159    return (data);
 160}
 161
 162/*----------------------------------------------------------------------------*/
 163
 164int mpc107_i2c_write_byte (
 165    unsigned char device,
 166    unsigned char block,
 167    unsigned char offset,
 168    unsigned char val )
 169{
 170
 171    unsigned long timeout = MPC107_I2C_TIMEOUT;
 172
 173    if (!mpc107_eumb_addr)
 174        return -6;
 175
 176    mpc107_i2c_wait_idle(timeout);
 177
 178    /* Start with MEN */
 179    out32r(MPC107_I2CCR, 0x80);
 180
 181    /* Start as master */
 182    out32r(MPC107_I2CCR, 0xB0);
 183    out32r(MPC107_I2CDR, (0xA0 | device | block));
 184
 185    if (mpc107_i2c_wait(timeout) < 0)
 186    {
 187        printf("mpc107_i2c_write Error 1\n");
 188        return -1;
 189    }
 190
 191    /* Data address */
 192    out32r(MPC107_I2CDR, offset);
 193
 194    if (mpc107_i2c_wait(timeout) < 0)
 195    {
 196        printf("mpc107_i2c_write Error 2\n");
 197        return -1;
 198    }
 199
 200    /* Write */
 201    out32r(MPC107_I2CDR, val);
 202    if (mpc107_i2c_wait(timeout) < 0)
 203    {
 204        printf("mpc107_i2c_write Error 3\n");
 205        return -1;
 206    }
 207
 208    /* Generate Stop Condition */
 209    out32r(MPC107_I2CCR, 0x80);
 210
 211    /* Return ACK or no ACK */
 212    return (in32r(MPC107_I2CSR) & 0x01);
 213}
 214
 215/*----------------------------------------------------------------------------*/
 216
 217int mpc107_srom_load (
 218    unsigned char addr,
 219    unsigned char *pBuf,
 220    int          cnt,
 221    unsigned char device,
 222    unsigned char block )
 223{
 224    register int i;
 225    int val;
 226    int timeout;
 227
 228    for (i = 0; i < cnt; i++)
 229    {
 230        timeout=100;
 231        do
 232        {
 233            val = mpc107_i2c_read_byte (device, block, addr);
 234            if (val < -1)
 235            {
 236            printf("i2c_read_error %d at dev %x block %x addr %x\n",
 237                   val, device, block, addr);
 238            return -1;
 239            }
 240            else if (timeout==0)
 241            {
 242                printf ("i2c_read_error: timeout at dev %x block %x addr %x\n",
 243                        device, block, addr);
 244                return -1;
 245            }
 246            timeout--;
 247        } while (val == -1); /* if no ack: try again! */
 248
 249        *pBuf++ = (unsigned char)val;
 250        addr++;
 251
 252        if ((addr == 0) && (i != cnt-1))    /* is it the same block ? */
 253        {
 254            if (block == FIRST_BLOCK)
 255                block = SECOND_BLOCK;
 256            else
 257            {
 258                printf ("ic2_read_error: read beyond 2. block !\n");
 259                return -1;
 260            }
 261        }
 262    }
 263    udelay(100000);
 264    return (cnt);
 265}
 266
 267/*----------------------------------------------------------------------------*/
 268
 269int mpc107_srom_store (
 270    unsigned char addr,
 271    unsigned char *pBuf,
 272    int          cnt,
 273    unsigned char device,
 274    unsigned char block )
 275{
 276    register int i;
 277
 278    for (i = 0; i < cnt; i++)
 279    {
 280        while (mpc107_i2c_write_byte (device,block,addr,*pBuf) == 1);
 281        addr++;
 282        pBuf++;
 283
 284        if ((addr == 0) && (i != cnt-1))     /* is it the same block ? */
 285        {
 286            if (block == FIRST_BLOCK)
 287                block = SECOND_BLOCK;
 288            else
 289            {
 290                printf ("ic2_write_error: write beyond 2. block !\n");
 291                return -1;
 292            }
 293        }
 294    }
 295    udelay(100000);
 296    return(cnt);
 297}
 298
 299/*----------------------------------------------------------------------------*/
 300
 301int mpc107_i2c_init ( unsigned long eumb_addr, unsigned long divider )
 302{
 303    unsigned long x;
 304
 305    if (eumb_addr)
 306        mpc107_eumb_addr = eumb_addr;
 307    else
 308        return -1;
 309
 310    /* Set I2C clock */
 311    x = in32r(MPC107_I2CFDR) & 0xffffff00;
 312    out32r(MPC107_I2CFDR, (x | divider));
 313
 314    /* Clear arbitration */
 315    out32r(MPC107_I2CSR, 0);
 316
 317    return mpc107_eumb_addr;
 318}
 319
 320/*----------------------------------------------------------------------------*/
 321