Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / eltec / elppc / mpc107_i2c.c
diff --git a/qemu/roms/u-boot/board/eltec/elppc/mpc107_i2c.c b/qemu/roms/u-boot/board/eltec/elppc/mpc107_i2c.c
new file mode 100644 (file)
index 0000000..4f95703
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * (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;
+}
+
+/*----------------------------------------------------------------------------*/