2005-11-10 17:26:51 +03:00
/*
* linux / arch / arm / mach - omap2 / id . c
*
* OMAP2 CPU identification code
*
* Copyright ( C ) 2005 Nokia Corporation
* Written by Tony Lindgren < tony @ atomide . com >
*
2009-05-29 01:16:04 +04:00
* Copyright ( C ) 2009 Texas Instruments
* Added OMAP4 support - Santosh Shilimkar < santosh . shilimkar @ ti . com >
*
2005-11-10 17:26:51 +03:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2005-11-10 17:26:51 +03:00
2008-08-10 21:08:10 +04:00
# include <asm/cputype.h>
2005-11-10 17:26:51 +03:00
2008-10-06 16:49:16 +04:00
# include <mach/common.h>
2008-08-05 19:14:15 +04:00
# include <mach/control.h>
# include <mach/cpu.h>
2006-12-07 04:14:05 +03:00
2008-07-03 13:24:45 +04:00
static struct omap_chip_id omap_chip ;
2008-12-11 04:36:31 +03:00
static unsigned int omap_revision ;
unsigned int omap_rev ( void )
{
return omap_revision ;
}
EXPORT_SYMBOL ( omap_rev ) ;
2008-07-03 13:24:45 +04:00
/**
* omap_chip_is - test whether currently running OMAP matches a chip type
* @ oc : omap_chip_t to test against
*
* Test whether the currently - running OMAP chip matches the supplied
* chip type ' oc ' . Returns 1 upon a match ; 0 upon failure .
*/
int omap_chip_is ( struct omap_chip_id oci )
{
return ( oci . oc & omap_chip . oc ) ? 1 : 0 ;
}
EXPORT_SYMBOL ( omap_chip_is ) ;
2009-06-23 14:30:23 +04:00
int omap_type ( void )
{
u32 val = 0 ;
if ( cpu_is_omap24xx ( ) )
val = omap_ctrl_readl ( OMAP24XX_CONTROL_STATUS ) ;
else if ( cpu_is_omap34xx ( ) )
val = omap_ctrl_readl ( OMAP343X_CONTROL_STATUS ) ;
else {
pr_err ( " Cannot detect omap type! \n " ) ;
goto out ;
}
val & = OMAP2_DEVICETYPE_MASK ;
val > > = 8 ;
out :
return val ;
}
EXPORT_SYMBOL ( omap_type ) ;
2008-12-11 04:36:30 +03:00
/*----------------------------------------------------------------------------*/
2008-07-03 13:24:45 +04:00
2008-12-11 04:36:30 +03:00
# define OMAP_TAP_IDCODE 0x0204
# define OMAP_TAP_DIE_ID_0 0x0218
# define OMAP_TAP_DIE_ID_1 0x021C
# define OMAP_TAP_DIE_ID_2 0x0220
# define OMAP_TAP_DIE_ID_3 0x0224
2008-07-03 13:24:45 +04:00
2008-12-11 04:36:30 +03:00
# define read_tap_reg(reg) __raw_readl(tap_base + (reg))
2008-07-03 13:24:45 +04:00
2008-12-11 04:36:30 +03:00
struct omap_id {
u16 hawkeye ; /* Silicon type (Hawkeye id) */
u8 dev ; /* Device type from production_id reg */
2008-12-11 04:36:31 +03:00
u32 type ; /* Combined type id copied to omap_revision */
2008-12-11 04:36:30 +03:00
} ;
2008-07-03 13:24:45 +04:00
2008-12-11 04:36:30 +03:00
/* Register values to detect the OMAP version */
static struct omap_id omap_ids [ ] __initdata = {
{ . hawkeye = 0xb5d9 , . dev = 0x0 , . type = 0x24200024 } ,
{ . hawkeye = 0xb5d9 , . dev = 0x1 , . type = 0x24201024 } ,
{ . hawkeye = 0xb5d9 , . dev = 0x2 , . type = 0x24202024 } ,
{ . hawkeye = 0xb5d9 , . dev = 0x4 , . type = 0x24220024 } ,
{ . hawkeye = 0xb5d9 , . dev = 0x8 , . type = 0x24230024 } ,
{ . hawkeye = 0xb68a , . dev = 0x0 , . type = 0x24300024 } ,
} ;
2008-07-03 13:24:45 +04:00
2008-12-11 04:36:30 +03:00
static void __iomem * tap_base ;
static u16 tap_prod_id ;
2005-11-10 17:26:51 +03:00
2008-12-11 04:36:30 +03:00
void __init omap24xx_check_revision ( void )
2005-11-10 17:26:51 +03:00
{
int i , j ;
2008-12-11 04:36:30 +03:00
u32 idcode , prod_id ;
2005-11-10 17:26:51 +03:00
u16 hawkeye ;
2008-12-11 04:36:30 +03:00
u8 dev_type , rev ;
2005-11-10 17:26:51 +03:00
idcode = read_tap_reg ( OMAP_TAP_IDCODE ) ;
2008-10-06 16:49:16 +04:00
prod_id = read_tap_reg ( tap_prod_id ) ;
2005-11-10 17:26:51 +03:00
hawkeye = ( idcode > > 12 ) & 0xffff ;
rev = ( idcode > > 28 ) & 0x0f ;
dev_type = ( prod_id > > 16 ) & 0x0f ;
2008-07-03 13:24:45 +04:00
pr_debug ( " OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x \n " ,
idcode , rev , hawkeye , ( idcode > > 1 ) & 0x7ff ) ;
pr_debug ( " OMAP_TAP_DIE_ID_0: 0x%08x \n " ,
read_tap_reg ( OMAP_TAP_DIE_ID_0 ) ) ;
pr_debug ( " OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i \n " ,
read_tap_reg ( OMAP_TAP_DIE_ID_1 ) ,
( read_tap_reg ( OMAP_TAP_DIE_ID_1 ) > > 28 ) & 0xf ) ;
pr_debug ( " OMAP_TAP_DIE_ID_2: 0x%08x \n " ,
read_tap_reg ( OMAP_TAP_DIE_ID_2 ) ) ;
pr_debug ( " OMAP_TAP_DIE_ID_3: 0x%08x \n " ,
read_tap_reg ( OMAP_TAP_DIE_ID_3 ) ) ;
pr_debug ( " OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i \n " ,
prod_id , dev_type ) ;
2005-11-10 17:26:51 +03:00
/* Check hawkeye ids */
for ( i = 0 ; i < ARRAY_SIZE ( omap_ids ) ; i + + ) {
if ( hawkeye = = omap_ids [ i ] . hawkeye )
break ;
}
if ( i = = ARRAY_SIZE ( omap_ids ) ) {
printk ( KERN_ERR " Unknown OMAP CPU id \n " ) ;
return ;
}
for ( j = i ; j < ARRAY_SIZE ( omap_ids ) ; j + + ) {
if ( dev_type = = omap_ids [ j ] . dev )
break ;
}
if ( j = = ARRAY_SIZE ( omap_ids ) ) {
printk ( KERN_ERR " Unknown OMAP device type. "
" Handling it as OMAP%04x \n " ,
omap_ids [ i ] . type > > 16 ) ;
j = i ;
}
2008-12-11 04:36:31 +03:00
pr_info ( " OMAP%04x " , omap_rev ( ) > > 16 ) ;
if ( ( omap_rev ( ) > > 8 ) & 0x0f )
pr_info ( " ES%x " , ( omap_rev ( ) > > 12 ) & 0xf ) ;
2008-07-03 13:24:45 +04:00
pr_info ( " \n " ) ;
2008-12-11 04:36:30 +03:00
}
void __init omap34xx_check_revision ( void )
{
u32 cpuid , idcode ;
u16 hawkeye ;
u8 rev ;
char * rev_name = " ES1.0 " ;
/*
* We cannot access revision registers on ES1 .0 .
* If the processor type is Cortex - A8 and the revision is 0x0
* it means its Cortex r0p0 which is 3430 ES1 .0 .
*/
cpuid = read_cpuid ( CPUID_ID ) ;
if ( ( ( ( cpuid > > 4 ) & 0xfff ) = = 0xc08 ) & & ( ( cpuid & 0xf ) = = 0x0 ) ) {
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES1_0 ;
2008-12-11 04:36:30 +03:00
goto out ;
}
/*
* Detection for 34 xx ES2 .0 and above can be done with just
* hawkeye and rev . See TRM 1.5 .2 Device Identification .
* Note that rev does not map directly to our defined processor
* revision numbers as ES1 .0 uses value 0.
*/
idcode = read_tap_reg ( OMAP_TAP_IDCODE ) ;
hawkeye = ( idcode > > 12 ) & 0xffff ;
rev = ( idcode > > 28 ) & 0xff ;
2008-07-03 13:24:45 +04:00
2008-12-11 04:36:30 +03:00
if ( hawkeye = = 0xb7ae ) {
switch ( rev ) {
case 0 :
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES2_0 ;
2008-12-11 04:36:30 +03:00
rev_name = " ES2.0 " ;
break ;
case 2 :
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES2_1 ;
2008-12-11 04:36:30 +03:00
rev_name = " ES2.1 " ;
break ;
case 3 :
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES3_0 ;
2008-12-11 04:36:30 +03:00
rev_name = " ES3.0 " ;
break ;
2009-01-29 19:57:16 +03:00
case 4 :
omap_revision = OMAP3430_REV_ES3_1 ;
rev_name = " ES3.1 " ;
break ;
2008-12-11 04:36:30 +03:00
default :
/* Use the latest known revision as default */
2009-01-29 19:57:16 +03:00
omap_revision = OMAP3430_REV_ES3_1 ;
2008-12-11 04:36:30 +03:00
rev_name = " Unknown revision \n " ;
}
}
out :
2008-12-11 04:36:31 +03:00
pr_info ( " OMAP%04x %s \n " , omap_rev ( ) > > 16 , rev_name ) ;
2005-11-10 17:26:51 +03:00
}
2008-12-11 04:36:30 +03:00
/*
* Try to detect the exact revision of the omap we ' re running on
*/
2008-12-11 04:36:30 +03:00
void __init omap2_check_revision ( void )
{
2008-12-11 04:36:30 +03:00
/*
* At this point we have an idea about the processor revision set
* earlier with omap2_set_globals_tap ( ) .
*/
if ( cpu_is_omap24xx ( ) )
omap24xx_check_revision ( ) ;
else if ( cpu_is_omap34xx ( ) )
omap34xx_check_revision ( ) ;
2009-05-29 01:16:04 +04:00
else if ( cpu_is_omap44xx ( ) ) {
printk ( KERN_INFO " FIXME: CPU revision = OMAP4430 \n " ) ;
return ;
} else
2008-12-11 04:36:30 +03:00
pr_err ( " OMAP revision unknown, please fix! \n " ) ;
/*
* OK , now we know the exact revision . Initialize omap_chip bits
* for powerdowmain and clockdomain code .
*/
if ( cpu_is_omap243x ( ) ) {
/* Currently only supports 2430ES2.1 and 2430-all */
omap_chip . oc | = CHIP_IS_OMAP2430 ;
} else if ( cpu_is_omap242x ( ) ) {
/* Currently only supports 2420ES2.1.1 and 2420-all */
omap_chip . oc | = CHIP_IS_OMAP2420 ;
} else if ( cpu_is_omap343x ( ) ) {
omap_chip . oc = CHIP_IS_OMAP3430 ;
2008-12-11 04:36:31 +03:00
if ( omap_rev ( ) = = OMAP3430_REV_ES1_0 )
2008-12-11 04:36:30 +03:00
omap_chip . oc | = CHIP_IS_OMAP3430ES1 ;
2009-02-06 06:45:25 +03:00
else if ( omap_rev ( ) > = OMAP3430_REV_ES2_0 & &
omap_rev ( ) < = OMAP3430_REV_ES2_1 )
2008-12-11 04:36:30 +03:00
omap_chip . oc | = CHIP_IS_OMAP3430ES2 ;
2009-02-06 06:45:25 +03:00
else if ( omap_rev ( ) = = OMAP3430_REV_ES3_0 )
omap_chip . oc | = CHIP_IS_OMAP3430ES3_0 ;
else if ( omap_rev ( ) = = OMAP3430_REV_ES3_1 )
omap_chip . oc | = CHIP_IS_OMAP3430ES3_1 ;
2008-12-11 04:36:30 +03:00
} else {
pr_err ( " Uninitialized omap_chip, please fix! \n " ) ;
}
2008-12-11 04:36:30 +03:00
}
2008-12-11 04:36:30 +03:00
/*
* Set up things for map_io and processor detection later on . Gets called
* pretty much first thing from board init . For multi - omap , this gets
* cpu_is_omapxxxx ( ) working accurately enough for map_io . Then we ' ll try to
* detect the exact revision later on in omap2_detect_revision ( ) once map_io
* is done .
*/
2008-10-06 16:49:16 +04:00
void __init omap2_set_globals_tap ( struct omap_globals * omap2_globals )
{
2008-12-11 04:36:31 +03:00
omap_revision = omap2_globals - > class ;
2008-10-06 16:49:16 +04:00
tap_base = omap2_globals - > tap ;
2008-12-11 04:36:30 +03:00
if ( cpu_is_omap34xx ( ) )
2008-10-06 16:49:16 +04:00
tap_prod_id = 0x0210 ;
else
tap_prod_id = 0x0208 ;
}