2007-08-22 00:34:16 +04:00
/*
* Thomas Horsten < thh @ lasat . com >
* Copyright ( C ) 2000 LASAT Networks A / S .
*
* This program is free software ; you can distribute it and / or modify it
* under the terms of the GNU General Public License ( Version 2 ) as
* published by the Free Software Foundation .
*
* This program is distributed in the hope 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 .
*
* Routines specific to the LASAT boards
*/
# include <linux/types.h>
# include <linux/crc32.h>
# include <asm/lasat/lasat.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/ctype.h>
2008-06-15 05:17:11 +04:00
# include <linux/mutex.h>
2007-08-22 00:34:16 +04:00
# include <asm/addrspace.h>
# include "at93c.h"
/* New model description table */
# include "lasat_models.h"
2008-06-15 05:17:11 +04:00
static DEFINE_MUTEX ( lasat_eeprom_mutex ) ;
2007-08-22 00:34:16 +04:00
# define EEPROM_CRC(data, len) (~crc32(~0, data, len))
struct lasat_info lasat_board_info ;
int EEPROMRead ( unsigned int pos , unsigned char * data , int len )
{
int i ;
for ( i = 0 ; i < len ; i + + )
* data + + = at93c_read ( pos + + ) ;
return 0 ;
}
int EEPROMWrite ( unsigned int pos , unsigned char * data , int len )
{
int i ;
for ( i = 0 ; i < len ; i + + )
at93c_write ( pos + + , * data + + ) ;
return 0 ;
}
static void init_flash_sizes ( void )
{
unsigned long * lb = lasat_board_info . li_flashpart_base ;
unsigned long * ls = lasat_board_info . li_flashpart_size ;
int i ;
ls [ LASAT_MTD_BOOTLOADER ] = 0x40000 ;
ls [ LASAT_MTD_SERVICE ] = 0xC0000 ;
ls [ LASAT_MTD_NORMAL ] = 0x100000 ;
2008-07-14 18:58:47 +04:00
if ( ! IS_LASAT_200 ( ) ) {
2007-08-22 00:34:16 +04:00
lasat_board_info . li_flash_base = 0x1e000000 ;
lb [ LASAT_MTD_BOOTLOADER ] = 0x1e400000 ;
if ( lasat_board_info . li_flash_size > 0x200000 ) {
ls [ LASAT_MTD_CONFIG ] = 0x100000 ;
ls [ LASAT_MTD_FS ] = 0x500000 ;
}
} else {
lasat_board_info . li_flash_base = 0x10000000 ;
if ( lasat_board_info . li_flash_size < 0x1000000 ) {
lb [ LASAT_MTD_BOOTLOADER ] = 0x10000000 ;
ls [ LASAT_MTD_CONFIG ] = 0x100000 ;
if ( lasat_board_info . li_flash_size > = 0x400000 )
ls [ LASAT_MTD_FS ] =
lasat_board_info . li_flash_size - 0x300000 ;
}
}
for ( i = 1 ; i < LASAT_MTD_LAST ; i + + )
lb [ i ] = lb [ i - 1 ] + ls [ i - 1 ] ;
}
int lasat_init_board_info ( void )
{
int c ;
unsigned long crc ;
unsigned long cfg0 , cfg1 ;
const struct product_info * ppi ;
int i_n_base_models = N_BASE_MODELS ;
const char * const * i_txt_base_models = txt_base_models ;
int i_n_prids = N_PRIDS ;
memset ( & lasat_board_info , 0 , sizeof ( lasat_board_info ) ) ;
/* First read the EEPROM info */
EEPROMRead ( 0 , ( unsigned char * ) & lasat_board_info . li_eeprom_info ,
sizeof ( struct lasat_eeprom_struct ) ) ;
/* Check the CRC */
crc = EEPROM_CRC ( ( unsigned char * ) ( & lasat_board_info . li_eeprom_info ) ,
sizeof ( struct lasat_eeprom_struct ) - 4 ) ;
if ( crc ! = lasat_board_info . li_eeprom_info . crc32 ) {
printk ( KERN_WARNING " WARNING... \n WARNING... \n EEPROM CRC does "
" not match calculated, attempting to soldier on... \n " ) ;
}
if ( lasat_board_info . li_eeprom_info . version ! = LASAT_EEPROM_VERSION ) {
printk ( KERN_WARNING " WARNING... \n WARNING... \n EEPROM version "
" %d, wanted version %d, attempting to soldier on... \n " ,
( unsigned int ) lasat_board_info . li_eeprom_info . version ,
LASAT_EEPROM_VERSION ) ;
}
cfg0 = lasat_board_info . li_eeprom_info . cfg [ 0 ] ;
cfg1 = lasat_board_info . li_eeprom_info . cfg [ 1 ] ;
if ( LASAT_W0_DSCTYPE ( cfg0 ) ! = 1 ) {
printk ( KERN_WARNING " WARNING... \n WARNING... \n "
" Invalid configuration read from EEPROM, attempting to "
" soldier on... " ) ;
}
/* We have a valid configuration */
switch ( LASAT_W0_SDRAMBANKSZ ( cfg0 ) ) {
case 0 :
lasat_board_info . li_memsize = 0x0800000 ;
break ;
case 1 :
lasat_board_info . li_memsize = 0x1000000 ;
break ;
case 2 :
lasat_board_info . li_memsize = 0x2000000 ;
break ;
case 3 :
lasat_board_info . li_memsize = 0x4000000 ;
break ;
case 4 :
lasat_board_info . li_memsize = 0x8000000 ;
break ;
default :
lasat_board_info . li_memsize = 0 ;
}
switch ( LASAT_W0_SDRAMBANKS ( cfg0 ) ) {
case 0 :
break ;
case 1 :
lasat_board_info . li_memsize * = 2 ;
break ;
default :
break ;
}
switch ( LASAT_W0_BUSSPEED ( cfg0 ) ) {
case 0x0 :
lasat_board_info . li_bus_hz = 60000000 ;
break ;
case 0x1 :
lasat_board_info . li_bus_hz = 66000000 ;
break ;
case 0x2 :
lasat_board_info . li_bus_hz = 66666667 ;
break ;
case 0x3 :
lasat_board_info . li_bus_hz = 80000000 ;
break ;
case 0x4 :
lasat_board_info . li_bus_hz = 83333333 ;
break ;
case 0x5 :
lasat_board_info . li_bus_hz = 100000000 ;
break ;
}
switch ( LASAT_W0_CPUCLK ( cfg0 ) ) {
case 0x0 :
lasat_board_info . li_cpu_hz =
lasat_board_info . li_bus_hz ;
break ;
case 0x1 :
lasat_board_info . li_cpu_hz =
lasat_board_info . li_bus_hz +
( lasat_board_info . li_bus_hz > > 1 ) ;
break ;
case 0x2 :
lasat_board_info . li_cpu_hz =
lasat_board_info . li_bus_hz +
lasat_board_info . li_bus_hz ;
break ;
case 0x3 :
lasat_board_info . li_cpu_hz =
lasat_board_info . li_bus_hz +
lasat_board_info . li_bus_hz +
( lasat_board_info . li_bus_hz > > 1 ) ;
break ;
case 0x4 :
lasat_board_info . li_cpu_hz =
lasat_board_info . li_bus_hz +
lasat_board_info . li_bus_hz +
lasat_board_info . li_bus_hz ;
break ;
}
/* Flash size */
switch ( LASAT_W1_FLASHSIZE ( cfg1 ) ) {
case 0 :
lasat_board_info . li_flash_size = 0x200000 ;
break ;
case 1 :
lasat_board_info . li_flash_size = 0x400000 ;
break ;
case 2 :
lasat_board_info . li_flash_size = 0x800000 ;
break ;
case 3 :
lasat_board_info . li_flash_size = 0x1000000 ;
break ;
case 4 :
lasat_board_info . li_flash_size = 0x2000000 ;
break ;
}
init_flash_sizes ( ) ;
lasat_board_info . li_bmid = LASAT_W0_BMID ( cfg0 ) ;
lasat_board_info . li_prid = lasat_board_info . li_eeprom_info . prid ;
if ( lasat_board_info . li_prid = = 0xffff | | lasat_board_info . li_prid = = 0 )
lasat_board_info . li_prid = lasat_board_info . li_bmid ;
/* Base model stuff */
if ( lasat_board_info . li_bmid > i_n_base_models )
lasat_board_info . li_bmid = i_n_base_models ;
strcpy ( lasat_board_info . li_bmstr ,
i_txt_base_models [ lasat_board_info . li_bmid ] ) ;
/* Product ID dependent values */
c = lasat_board_info . li_prid ;
if ( c > = i_n_prids ) {
strcpy ( lasat_board_info . li_namestr , " Unknown Model " ) ;
strcpy ( lasat_board_info . li_typestr , " Unknown Type " ) ;
} else {
ppi = & vendor_info_table [ 0 ] . vi_product_info [ c ] ;
strcpy ( lasat_board_info . li_namestr , ppi - > pi_name ) ;
if ( ppi - > pi_type )
strcpy ( lasat_board_info . li_typestr , ppi - > pi_type ) ;
else
sprintf ( lasat_board_info . li_typestr , " %d " , 10 * c ) ;
}
return 0 ;
}
void lasat_write_eeprom_info ( void )
{
unsigned long crc ;
2008-06-15 05:17:11 +04:00
mutex_lock ( & lasat_eeprom_mutex ) ;
2007-08-22 00:34:16 +04:00
/* Generate the CRC */
crc = EEPROM_CRC ( ( unsigned char * ) ( & lasat_board_info . li_eeprom_info ) ,
sizeof ( struct lasat_eeprom_struct ) - 4 ) ;
lasat_board_info . li_eeprom_info . crc32 = crc ;
/* Write the EEPROM info */
EEPROMWrite ( 0 , ( unsigned char * ) & lasat_board_info . li_eeprom_info ,
sizeof ( struct lasat_eeprom_struct ) ) ;
2008-06-15 05:17:11 +04:00
mutex_unlock ( & lasat_eeprom_mutex ) ;
2007-08-22 00:34:16 +04:00
}