@ -1,63 +1,86 @@
/*
* This file is for AT24C64 eeprom .
* Author : lius haozong
* Author : Liu S haozong
*/
# include <sys/linux/types.h>
# include <pmon.h>
# include <stdio.h>
# include <machine/pio.h>
# include "target/ls2h.h"
# include "target/board.h"
# include "target/eeprom.h"
# define AT24C64_ADDR 0xa0
static void ls2h_i2c_stop ( )
# define PRER_LO_REG 0x0
# define PRER_HI_REG 0x1
# define CTR_REG 0x2
# define TXR_REG 0x3
# define RXR_REG 0x3
# define CR_REG 0x4
# define SR_REG 0x4
# define ee_outb(reg, val) outb(base + reg, val)
# define ee_inb(reg) inb(base + reg)
static unsigned char random_num ( )
{
int tmp ;
__asm__ volatile (
" mfc0 %0, $9 \r \n "
: : " r " ( tmp )
) ;
return tmp & 0xf ;
}
static void ls2h_i2c_stop ( u32 base )
{
again :
write_reg_byte ( LS2H_I2C1_CR_REG , CR_STOP ) ;
read_reg_byte ( LS2H_I2C1_SR_REG ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_BUSY )
ee_outb ( CR_REG , CR_STOP ) ;
ee_in b ( SR_REG ) ;
while ( ee_in b ( SR_REG ) & SR_BUSY )
goto again ;
}
void ls2h_i2c1_init ( )
void i2c_init ( )
{
u32 base = ( board_ver_num = = LS3A2H_BOARD_OLD ) ?
LS2H_I2C1_REG_BASE : LS2H_I2C0_REG_BASE ;
ee_outb ( CTR_REG , 0x0 ) ;
ee_outb ( PRER_LO_REG , 0x2c ) ;
ee_outb ( PRER_HI_REG , 0x1 ) ;
ee_outb ( CTR_REG , 0x80 ) ;
}
static int i2c_tx_byte ( u32 base , unsigned char data , unsigned char opt )
{
write_reg_byte ( LS2H_I2C1_CTR_REG , 0x0 ) ;
write_reg_byte ( LS2H_I2C1_PRER_LO_REG , 0x2c ) ;
write_reg_byte ( LS2H_I2C1_PRER_HI_REG , 0x1 ) ;
write_reg_byte ( LS2H_I2C1_CTR_REG , 0x80 ) ;
ee_outb ( TXR_REG , data ) ;
ee_outb ( CR_REG , opt ) ;
while ( ee_inb ( SR_REG ) & SR_TIP ) ;
if ( ee_inb ( SR_REG ) & SR_NOACK ) {
printf ( " Eeprom has no ack, Pls check the hardware! \n " ) ;
ls2h_i2c_stop ( base ) ;
return - 1 ;
}
return 0 ;
}
static int i2c_send_addr ( int data_addr )
static int i2c_send_addr ( u32 base , int data_addr )
{
unsigned char ee_dev_addr = AT24C64_ADDR ;
int i = ( data_addr > > 8 ) & 0x1f ;
write_reg_byte ( LS2H_I2C1_TXR_REG , ee_dev_addr ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , ( CR_START | CR_WRITE ) ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ , __LINE__ ) ;
ls2h_i2c_stop ( ) ;
if ( i2c_tx_byte ( base , ee_dev_addr , CR_START | CR_WRITE ) < 0 )
return 0 ;
}
write_reg_byte ( LS2H_I2C1_TXR_REG , ( i & 0xff ) ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , CR_WRITE ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ , __LINE__ ) ;
ls2h_i2c_stop ( ) ;
if ( i2c_tx_byte ( base , i & 0xff , CR_WRITE ) < 0 )
return 0 ;
}
write_reg_byte ( LS2H_I2C1_TXR_REG , ( data_addr & 0xff ) ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , CR_WRITE ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ , __LINE__ ) ;
ls2h_i2c_stop ( ) ;
if ( i2c_tx_byte ( base , data_addr & 0xff , CR_WRITE ) < 0 )
return 0 ;
}
return 1 ;
}
@ -71,25 +94,16 @@ static int i2c_send_addr(int data_addr)
* the write sequence with a stop condition .
*
* */
int eeprom_write_byte ( int data_addr , unsigned char * buf )
int eeprom_write_byte ( u32 base , int data_addr , unsigned char * buf )
{
int i ;
i = i2c_send_addr ( data_addr ) ;
if ( ! i ) {
printf ( " %s:%d send addr failed! \n " , __func__ , __LINE__ ) ;
if ( ! i2c_send_addr ( base , data_addr ) )
return 0 ;
}
write_reg_byte ( LS2H_I2C1_TXR_REG , ( * buf & 0xff ) ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , CR_WRITE ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ , __LINE__ ) ;
ls2h_i2c_stop ( ) ;
if ( i2c_tx_byte ( base , * buf & 0xff , CR_WRITE ) < 0 )
return 0 ;
}
ls2h_i2c_stop ( ) ;
ls2h_i2c_stop ( base ) ;
return 1 ;
}
@ -104,29 +118,18 @@ int eeprom_write_byte(int data_addr, unsigned char *buf)
* to the EEPROM , the data word address will " roll over " and previous data will be
* overwritten .
* */
int eeprom_write_page ( int data_addr , unsigned char * buf , int count )
int eeprom_write_page ( u32 base , int data_addr , unsigned char * buf , int count )
{
int i ;
i = i2c_send_addr ( data_addr ) ;
if ( ! i ) {
printf ( " %s:%d send addr error! \n " , __func__ , __LINE__ ) ;
if ( ! i2c_send_addr ( base , data_addr ) )
return 0 ;
}
for ( i = 0 ; i < count ; i + + ) {
write_reg_byte ( LS2H_I2C1_TXR_REG , ( buf [ i ] & 0xff ) ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , CR_WRITE ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ ,
__LINE__ ) ;
ls2h_i2c_stop ( ) ;
for ( i = 0 ; i < count ; i + + )
if ( i2c_tx_byte ( base , buf [ i ] & 0xff , CR_WRITE ) < 0 )
return 0 ;
}
}
ls2h_i2c_stop ( ) ;
ls2h_i2c_stop ( base ) ;
return i ;
}
/*
@ -139,25 +142,18 @@ int eeprom_write_page(int data_addr, unsigned char *buf, int count)
* same page .
*
* */
int eeprom_read_cur ( unsigned char * buf )
int eeprom_read_cur ( u32 base , unsigned char * buf )
{
unsigned char ee_dev_addr = AT24C64_ADDR | 0x1 ;
write_reg_byte ( LS2H_I2C1_TXR_REG , ee_dev_addr ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , ( CR_START | CR_WRITE ) ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ , __LINE__ ) ;
ls2h_i2c_stop ( ) ;
if ( i2c_tx_byte ( base , ee_dev_addr , CR_START | CR_WRITE ) < 0 )
return 0 ;
}
write_reg_byte ( LS2H_I2C1_ CR_REG, CR_READ ) ;
while ( r ead_r eg _byte ( LS2H_I2C1_ SR_REG) & SR_TIP ) ;
ee_outb ( CR_REG , CR_READ ) ;
while ( ee_inb ( SR_REG ) & SR_TIP ) ;
* buf = r ead_r eg _byte ( LS2H_I2C1_ RXR_REG) ;
ls2h_i2c_stop ( ) ;
* buf = ee_inb ( RXR_REG ) ;
ls2h_i2c_stop ( base ) ;
return 1 ;
}
@ -172,22 +168,13 @@ int eeprom_read_cur(unsigned char *buf)
* does generate a following stop condition .
*
* */
int eeprom_read_rand ( int data_addr , unsigned char * buf )
int eeprom_read_rand ( u32 base , int data_addr , unsigned char * buf )
{
int i ;
i = i2c_send_addr ( data_addr ) ;
if ( ! i ) {
printf ( " %s:%d eeprpm random send addr error! \n " , __func__ ,
__LINE__ ) ;
if ( ! i2c_send_addr ( base , data_addr ) )
return 0 ;
}
i = eeprom_read_cur ( buf ) ;
if ( ! i ) {
printf ( " %s:%d eeprom random read failed! \n " , __func__ ,
__LINE__ ) ;
if ( ! eeprom_read_cur ( base , buf ) ) ;
return 0 ;
}
return 1 ;
}
@ -203,67 +190,90 @@ int eeprom_read_rand(int data_addr, unsigned char *buf)
* stop condition .
*
*/
static int i2c_read_seq_cur ( unsigned char * buf , int count )
static int i2c_read_seq_cur ( u32 base , unsigned char * buf , int count )
{
int i ;
unsigned char ee_dev_addr = AT24C64_ADDR | 0x1 ;
write_reg_byte ( LS2H_I2C1_TXR_REG , ee_dev_addr ) ;
write_reg_byte ( LS2H_I2C1_CR_REG , ( CR_START | CR_WRITE ) ) ;
while ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_TIP ) ;
if ( read_reg_byte ( LS2H_I2C1_SR_REG ) & SR_NOACK ) {
printf ( " %s:%d eeprom has no ack \n " , __func__ , __LINE__ ) ;
ls2h_i2c_stop ( ) ;
if ( i2c_tx_byte ( base , ee_dev_addr , CR_START | CR_WRITE ) < 0 )
return 0 ;
}
for ( i = 0 ; i < count ; i + + ) {
write_reg_byte ( LS2H_I2C1_CR_REG ,
( ( i = = count - 1 ) ? ( CR_READ | CR_ACK ) : CR_READ ) ) ;
while ( r ead_r eg _byte ( LS2H_I2C1_ SR_REG) & SR_TIP ) ;
buf [ i ] = r ead_r eg _byte ( LS2H_I2C1_ RXR_REG) ;
ee_outb ( CR_REG , ( ( i = = count - 1 ) ?
( CR_READ | CR_ACK ) : CR_READ ) ) ;
while ( ee_inb ( SR_REG ) & SR_TIP ) ;
buf [ i ] = ee_in b ( RXR_REG ) ;
}
ls2h_i2c_stop ( ) ;
ls2h_i2c_stop ( base ) ;
return i ;
}
static int i2c_read_seq_rand ( int data_addr , unsigned char * buf , int count )
static int i2c_read_seq_rand ( u32 base , int data_addr ,
unsigned char * buf , int count )
{
int i ;
i = i2c_send_addr ( data_addr ) ;
if ( ! i ) {
printf ( " %s:%d send addr failed! \n " , __func__ , __LINE__ ) ;
return i ;
}
if ( ! i2c_send_addr ( base , data_addr ) )
return 0 ;
i = i2c_read_seq_cur ( buf , count ) ;
return i2c_read_seq_cur ( base , buf , count ) ;
}
if ( ! i ) {
printf ( " %s:%d eeprom random read failed! \n " , __func__ ,
__LINE__ ) ;
return 0 ;
}
int eeprom_read_seq ( u32 base , int data_addr , unsigned char * buf , int count )
{
int i ;
i = i2c_read_seq_rand ( base , data_addr , buf , count ) ;
return i ;
}
int eepro m_read_seq ( int data_addr , unsigned char * buf , int count )
int mac _read ( int data_addr , unsigned char * buf , int count )
{
int i ;
i = i2c_read_seq_rand ( data_addr , buf , count ) ;
u8 tmp ;
u32 base = ( board_ver_num = = LS3A2H_BOARD_OLD ) ?
LS2H_I2C1_REG_BASE : LS2H_I2C0_REG_BASE ;
i = eeprom_read_seq ( base , data_addr , buf , count ) ;
if ( ! i ) {
printf ( " get random MAC address: " ) ;
for ( i = 0 ; i < count ; i + + ) {
tmp = random_num ( ) ;
tmp = tmp < < 4 ;
tmp | = random_num ( ) ;
buf [ i ] = tmp ;
}
buf [ 0 ] & = 0xfe ; /* clear multicast bit */
buf [ 0 ] | = 0x02 ; /* set local assignment bit (IEEE802) */
for ( i = 0 ; i < count ; i + + )
printf ( " %02x%s " , buf [ i ] , ( i = = ( count - 1 ) ) ? " " : " : " ) ;
printf ( " \n " ) ;
}
return i ;
}
int mac_write ( int data_addr , unsigned char * buf , int count )
{
u32 base = ( board_ver_num = = LS3A2H_BOARD_OLD ) ?
LS2H_I2C1_REG_BASE : LS2H_I2C0_REG_BASE ;
return eeprom_write_page ( base , data_addr , buf , count ) ;
}
int cmd_eeprom_read ( int ac , unsigned char * av [ ] )
{
int i , data_addr , count ;
unsigned char buf [ 32 ] ;
u32 base = ( board_ver_num = = LS3A2H_BOARD_OLD ) ?
LS2H_I2C1_REG_BASE : LS2H_I2C0_REG_BASE ;
switch ( ac ) {
case 2 :
data_addr = strtoul ( av [ 1 ] , NULL , 0 ) ;
if ( eeprom_read_rand ( data_addr , buf ) )
if ( eeprom_read_rand ( base , data_addr , buf ) )
printf ( " %x: 0x%x \n " , data_addr , buf [ 0 ] ) ;
else
printf ( " eeprom read error! \n " ) ;
@ -272,7 +282,7 @@ int cmd_eeprom_read(int ac, unsigned char *av[])
case 3 :
data_addr = strtoul ( av [ 1 ] , NULL , 0 ) ;
count = strtoul ( av [ 2 ] , NULL , 0 ) ;
if ( eeprom_read_seq ( data_addr , buf , count ) = = count ) {
if ( eeprom_read_seq ( base , data_addr , buf , count ) = = count ) {
for ( i = 0 ; i < count ; i + + ) {
printf ( " %4x: 0x%02x \n " , data_addr + i , buf [ i ] ) ;
}
@ -282,18 +292,23 @@ int cmd_eeprom_read(int ac, unsigned char *av[])
}
return i ;
default :
printf ( " e2 pread @start_addr @count \n " ) ;
printf ( " ee pread @start_addr @count \n " ) ;
printf ( " read \" count \" bytes from eeprom at address: start_addr \n " ) ;
}
}
int cmd_eeprom_write ( int ac , unsigned char * av [ ] )
{
int i , v , count ;
unsigned char * s = NULL ;
unsigned char buf [ 32 ] ;
u32 base = ( board_ver_num = = LS3A2H_BOARD_OLD ) ?
LS2H_I2C1_REG_BASE : LS2H_I2C0_REG_BASE ;
int data_addr = strtoul ( av [ 1 ] , NULL , 0 ) ;
if ( av [ 2 ] ) s = av [ 2 ] ;
else {
if ( av [ 2 ] ) {
s = av [ 2 ] ;
} else {
printf ( " Please accord to correct format, for example: \n " ) ;
printf ( " \t eepwrite a0 \" 00 11 af \" \n " ) ;
printf ( " This means 0xa0 = 0x00; 0xa1 = 0x11; 0xa2 = 0xaf \n " ) ;
@ -308,7 +323,7 @@ int cmd_eeprom_write(int ac, unsigned char *av[])
s + = 3 ;
}
if ( eeprom_write_page ( data_addr , buf , count ) = = count )
if ( eeprom_write_page ( base , data_addr , buf , count ) = = count )
for ( i = 0 ; i < count ; i + + )
printf ( " %4x <= 0x%x \n " , data_addr + i , buf [ i ] ) ;
else
@ -319,15 +334,26 @@ int cmd_eeprom_write(int ac, unsigned char *av[])
int cmd_setmac ( int ac , unsigned char * av [ ] )
{
int i , j , v , count , data_addr ;
int i , j , v , count , data_addr , param ;
unsigned char * s = NULL ;
unsigned char buf [ 32 ] ;
data_addr = strtoul ( av [ 1 ] + 3 , NULL , 0 ) ;
data_addr * = 6 ;
u32 base = ( board_ver_num = = LS3A2H_BOARD_OLD ) ?
LS2H_I2C1_REG_BASE : LS2H_I2C0_REG_BASE ;
if ( ac = = 1 ) {
switch ( ac ) {
case 1 :
case 2 :
param = 1 ;
break ;
case 3 :
break ;
default :
goto warning ;
}
if ( param = = 1 ) {
for ( i = 0 ; i < 2 ; i + + ) {
if ( eeprom_read_seq ( i * 6 , buf , 6 ) = = 6 ) {
if ( eeprom_read_seq ( base , i * 6 , buf , 6 ) = = 6 ) {
printf ( " eth%d Mac address: " , i ) ;
for ( j = 0 ; j < 6 ; j + + )
printf ( " %02x%s " , buf [ j ] , ( 5 - j ) ? " : " : " " ) ;
@ -352,7 +378,9 @@ int cmd_setmac(int ac, unsigned char *av[])
s + = 3 ;
}
if ( eeprom_write_page ( data_addr , buf , count ) = = count ) {
data_addr = strtoul ( av [ 1 ] + 3 , NULL , 0 ) ;
data_addr * = 6 ;
if ( eeprom_write_page ( base , data_addr , buf , count ) = = count ) {
printf ( " set eth%d Mac address: %s \n " , data_addr / 6 , av [ 2 ] ) ;
printf ( " The machine should be restarted to make the mac change to take effect!! \n " ) ;
} else
@ -367,7 +395,6 @@ warning:
static const Cmd Cmds [ ] = {
{ " Misc " } ,
{ " i2c1init " , " " , NULL , " init LS2H I2C1 " , ls2h_i2c1_init , 1 , 5 , 0 } ,
{ " setmac " , " " , NULL , " set the Mac address of LS2H syn0 and syn1 " , cmd_setmac , 1 , 5 , 0 } ,
{ " eepread " , " " , NULL , " read a address from an eeprom chip " , cmd_eeprom_read ,
1 , 5 , 0 } ,