/* * (C) Copyright 2002 ELTEC Elektronik AG * Frank Gottschling * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ /* includes */ #include #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; } /*----------------------------------------------------------------------------*/