mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-14 08:57:58 +00:00
1a4596601f
Signed-off-by: Wolfgang Denk <wd@denx.de> [trini: Fixup common/cmd_io.c] Signed-off-by: Tom Rini <trini@ti.com>
304 lines
5.9 KiB
C
304 lines
5.9 KiB
C
/*
|
|
* (C) Copyright 2002 ELTEC Elektronik AG
|
|
* Frank Gottschling <fgottschling@eltec.de>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
/* includes */
|
|
#include <common.h>
|
|
#include "srom.h"
|
|
|
|
/* locals */
|
|
static unsigned long mpc107_eumb_addr = 0;
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
* calculate checksum for ELTEC revision srom
|
|
*/
|
|
unsigned long el_srom_checksum (ptr, size)
|
|
register unsigned char *ptr;
|
|
unsigned long size;
|
|
{
|
|
u_long f, accu = 0;
|
|
u_int i;
|
|
u_char byte;
|
|
|
|
for (; size; size--)
|
|
{
|
|
byte = *ptr++;
|
|
for (i = 8; i; i--)
|
|
{
|
|
f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
|
|
accu >>= 1; accu ^= f;
|
|
byte >>= 1;
|
|
}
|
|
}
|
|
return(accu);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
static int mpc107_i2c_wait ( unsigned long timeout )
|
|
{
|
|
unsigned long x;
|
|
|
|
while (((x = in32r(MPC107_I2CSR)) & 0x82) != 0x82)
|
|
{
|
|
if (!timeout--)
|
|
return -1;
|
|
}
|
|
|
|
if (x & 0x10)
|
|
{
|
|
return -1;
|
|
}
|
|
out32r(MPC107_I2CSR, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
static int mpc107_i2c_wait_idle ( unsigned long timeout )
|
|
{
|
|
while (in32r(MPC107_I2CSR) & 0x20)
|
|
{
|
|
if (!timeout--)
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
int mpc107_i2c_read_byte (
|
|
unsigned char device,
|
|
unsigned char block,
|
|
unsigned char offset )
|
|
{
|
|
unsigned long timeout = MPC107_I2C_TIMEOUT;
|
|
int data;
|
|
|
|
if (!mpc107_eumb_addr)
|
|
return -6;
|
|
|
|
mpc107_i2c_wait_idle (timeout);
|
|
|
|
/* Start with MEN */
|
|
out32r(MPC107_I2CCR, 0x80);
|
|
|
|
/* Start as master */
|
|
out32r(MPC107_I2CCR, 0xB0);
|
|
out32r(MPC107_I2CDR, (0xA0 | device | block));
|
|
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_read Error 1\n");
|
|
return -2;
|
|
}
|
|
|
|
if (in32r(MPC107_I2CSR)&0x1)
|
|
{
|
|
/* Generate STOP condition; device busy or not existing */
|
|
out32r(MPC107_I2CCR, 0x80);
|
|
return -1;
|
|
}
|
|
|
|
/* Data address */
|
|
out32r(MPC107_I2CDR, offset);
|
|
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_read Error 2\n");
|
|
return -3;
|
|
}
|
|
|
|
/* Switch to read - restart */
|
|
out32r(MPC107_I2CCR, 0xB4);
|
|
out32r(MPC107_I2CDR, (0xA1 | device | block));
|
|
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_read Error 3\n");
|
|
return -4;
|
|
}
|
|
|
|
out32r(MPC107_I2CCR, 0xA8); /* no ACK */
|
|
in32r(MPC107_I2CDR);
|
|
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_read Error 4\n");
|
|
return -5;
|
|
}
|
|
/* Generate STOP condition */
|
|
out32r(MPC107_I2CCR, 0x88);
|
|
|
|
/* read */
|
|
data = in32r(MPC107_I2CDR);
|
|
|
|
return (data);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
int mpc107_i2c_write_byte (
|
|
unsigned char device,
|
|
unsigned char block,
|
|
unsigned char offset,
|
|
unsigned char val )
|
|
{
|
|
|
|
unsigned long timeout = MPC107_I2C_TIMEOUT;
|
|
|
|
if (!mpc107_eumb_addr)
|
|
return -6;
|
|
|
|
mpc107_i2c_wait_idle(timeout);
|
|
|
|
/* Start with MEN */
|
|
out32r(MPC107_I2CCR, 0x80);
|
|
|
|
/* Start as master */
|
|
out32r(MPC107_I2CCR, 0xB0);
|
|
out32r(MPC107_I2CDR, (0xA0 | device | block));
|
|
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_write Error 1\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Data address */
|
|
out32r(MPC107_I2CDR, offset);
|
|
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_write Error 2\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Write */
|
|
out32r(MPC107_I2CDR, val);
|
|
if (mpc107_i2c_wait(timeout) < 0)
|
|
{
|
|
printf("mpc107_i2c_write Error 3\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Generate Stop Condition */
|
|
out32r(MPC107_I2CCR, 0x80);
|
|
|
|
/* Return ACK or no ACK */
|
|
return (in32r(MPC107_I2CSR) & 0x01);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
int mpc107_srom_load (
|
|
unsigned char addr,
|
|
unsigned char *pBuf,
|
|
int cnt,
|
|
unsigned char device,
|
|
unsigned char block )
|
|
{
|
|
register int i;
|
|
int val;
|
|
int timeout;
|
|
|
|
for (i = 0; i < cnt; i++)
|
|
{
|
|
timeout=100;
|
|
do
|
|
{
|
|
val = mpc107_i2c_read_byte (device, block, addr);
|
|
if (val < -1)
|
|
{
|
|
printf("i2c_read_error %d at dev %x block %x addr %x\n",
|
|
val, device, block, addr);
|
|
return -1;
|
|
}
|
|
else if (timeout==0)
|
|
{
|
|
printf ("i2c_read_error: timeout at dev %x block %x addr %x\n",
|
|
device, block, addr);
|
|
return -1;
|
|
}
|
|
timeout--;
|
|
} while (val == -1); /* if no ack: try again! */
|
|
|
|
*pBuf++ = (unsigned char)val;
|
|
addr++;
|
|
|
|
if ((addr == 0) && (i != cnt-1)) /* is it the same block ? */
|
|
{
|
|
if (block == FIRST_BLOCK)
|
|
block = SECOND_BLOCK;
|
|
else
|
|
{
|
|
printf ("ic2_read_error: read beyond 2. block !\n");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
udelay(100000);
|
|
return (cnt);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
int mpc107_srom_store (
|
|
unsigned char addr,
|
|
unsigned char *pBuf,
|
|
int cnt,
|
|
unsigned char device,
|
|
unsigned char block )
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i < cnt; i++)
|
|
{
|
|
while (mpc107_i2c_write_byte (device,block,addr,*pBuf) == 1);
|
|
addr++;
|
|
pBuf++;
|
|
|
|
if ((addr == 0) && (i != cnt-1)) /* is it the same block ? */
|
|
{
|
|
if (block == FIRST_BLOCK)
|
|
block = SECOND_BLOCK;
|
|
else
|
|
{
|
|
printf ("ic2_write_error: write beyond 2. block !\n");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
udelay(100000);
|
|
return(cnt);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
int mpc107_i2c_init ( unsigned long eumb_addr, unsigned long divider )
|
|
{
|
|
unsigned long x;
|
|
|
|
if (eumb_addr)
|
|
mpc107_eumb_addr = eumb_addr;
|
|
else
|
|
return -1;
|
|
|
|
/* Set I2C clock */
|
|
x = in32r(MPC107_I2CFDR) & 0xffffff00;
|
|
out32r(MPC107_I2CFDR, (x | divider));
|
|
|
|
/* Clear arbitration */
|
|
out32r(MPC107_I2CSR, 0);
|
|
|
|
return mpc107_eumb_addr;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|