2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2005-07-10 19:58:12 +01:00
/*
* linux / arch / arm / mach - omap1 / id . c
*
* OMAP1 CPU identification code
*
* Copyright ( C ) 2004 Nokia Corporation
* Written by Tony Lindgren < tony @ atomide . com >
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2012-03-28 18:30:01 +01:00
# include <asm/system_info.h>
2012-02-24 10:34:34 -08:00
2012-10-05 13:25:59 -07:00
# include "soc.h"
2005-07-10 19:58:12 +01:00
2012-02-24 10:34:35 -08:00
# include <mach/hardware.h>
2012-04-13 06:34:26 -06:00
# include "common.h"
2005-11-10 14:26:48 +00:00
# define OMAP_DIE_ID_0 0xfffe1800
# define OMAP_DIE_ID_1 0xfffe1804
# define OMAP_PRODUCTION_ID_0 0xfffe2000
# define OMAP_PRODUCTION_ID_1 0xfffe2004
# define OMAP32_ID_0 0xfffed400
# define OMAP32_ID_1 0xfffed404
2005-07-10 19:58:12 +01:00
struct omap_id {
u16 jtag_id ; /* Used to determine OMAP type */
u8 die_rev ; /* Processor revision */
u32 omap_id ; /* OMAP revision */
u32 type ; /* Cpu id bits [31:08], cpu class bits [07:00] */
} ;
2008-12-10 17:36:31 -08:00
static unsigned int omap_revision ;
2005-07-10 19:58:12 +01:00
/* Register values to detect the OMAP version */
static struct omap_id omap_ids [ ] __initdata = {
2005-11-10 14:26:48 +00:00
{ . jtag_id = 0xb574 , . die_rev = 0x2 , . omap_id = 0x03310315 , . type = 0x03100000 } ,
2005-07-10 19:58:12 +01:00
{ . jtag_id = 0x355f , . die_rev = 0x0 , . omap_id = 0x03320000 , . type = 0x07300100 } ,
{ . jtag_id = 0xb55f , . die_rev = 0x0 , . omap_id = 0x03320000 , . type = 0x07300300 } ,
2009-09-24 16:23:13 -07:00
{ . jtag_id = 0xb62c , . die_rev = 0x1 , . omap_id = 0x03320500 , . type = 0x08500000 } ,
2005-07-10 19:58:12 +01:00
{ . jtag_id = 0xb470 , . die_rev = 0x0 , . omap_id = 0x03310100 , . type = 0x15100000 } ,
{ . jtag_id = 0xb576 , . die_rev = 0x0 , . omap_id = 0x03320000 , . type = 0x16100000 } ,
{ . jtag_id = 0xb576 , . die_rev = 0x2 , . omap_id = 0x03320100 , . type = 0x16110000 } ,
{ . jtag_id = 0xb576 , . die_rev = 0x3 , . omap_id = 0x03320100 , . type = 0x16100c00 } ,
{ . jtag_id = 0xb576 , . die_rev = 0x0 , . omap_id = 0x03320200 , . type = 0x16100d00 } ,
{ . jtag_id = 0xb613 , . die_rev = 0x0 , . omap_id = 0x03320300 , . type = 0x1610ef00 } ,
{ . jtag_id = 0xb613 , . die_rev = 0x0 , . omap_id = 0x03320300 , . type = 0x1610ef00 } ,
{ . jtag_id = 0xb576 , . die_rev = 0x1 , . omap_id = 0x03320100 , . type = 0x16110000 } ,
{ . jtag_id = 0xb58c , . die_rev = 0x2 , . omap_id = 0x03320200 , . type = 0x16110b00 } ,
{ . jtag_id = 0xb58c , . die_rev = 0x3 , . omap_id = 0x03320200 , . type = 0x16110c00 } ,
{ . jtag_id = 0xb65f , . die_rev = 0x0 , . omap_id = 0x03320400 , . type = 0x16212300 } ,
{ . jtag_id = 0xb65f , . die_rev = 0x1 , . omap_id = 0x03320400 , . type = 0x16212300 } ,
{ . jtag_id = 0xb65f , . die_rev = 0x1 , . omap_id = 0x03320500 , . type = 0x16212300 } ,
{ . jtag_id = 0xb5f7 , . die_rev = 0x0 , . omap_id = 0x03330000 , . type = 0x17100000 } ,
{ . jtag_id = 0xb5f7 , . die_rev = 0x1 , . omap_id = 0x03330100 , . type = 0x17100000 } ,
{ . jtag_id = 0xb5f7 , . die_rev = 0x2 , . omap_id = 0x03330100 , . type = 0x17100000 } ,
} ;
2008-12-10 17:36:31 -08:00
unsigned int omap_rev ( void )
{
return omap_revision ;
}
EXPORT_SYMBOL ( omap_rev ) ;
2005-07-10 19:58:12 +01:00
/*
* Get OMAP type from PROD_ID .
* 1710 has the PROD_ID in bits 15 : 00 , not in 16 : 01 as documented in TRM .
* 1510 PROD_ID is empty , and 1610 PROD_ID does not make sense .
* Undocumented register in TEST BLOCK is used as fallback ; This seems to
* work on 1510 , 1610 & 1710. The official way hopefully will work in future
* processors .
*/
static u16 __init omap_get_jtag_id ( void )
{
u32 prod_id , omap_id ;
prod_id = omap_readl ( OMAP_PRODUCTION_ID_1 ) ;
omap_id = omap_readl ( OMAP32_ID_1 ) ;
2009-03-23 18:07:39 -07:00
/* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */
2005-07-10 19:58:12 +01:00
if ( ( ( prod_id > > 20 ) = = 0 ) | | ( prod_id = = omap_id ) )
prod_id = 0 ;
else
prod_id & = 0xffff ;
if ( prod_id )
return prod_id ;
/* Use OMAP32_ID_1 as fallback */
prod_id = ( ( omap_id > > 12 ) & 0xffff ) ;
return prod_id ;
}
/*
* Get OMAP revision from DIE_REV .
* Early 1710 processors may have broken OMAP_DIE_ID , it contains PROD_ID .
* Undocumented register in the TEST BLOCK is used as fallback .
* REVISIT : This does not seem to work on 1510
*/
static u8 __init omap_get_die_rev ( void )
{
u32 die_rev ;
die_rev = omap_readl ( OMAP_DIE_ID_1 ) ;
/* Check for broken OMAP_DIE_ID on early 1710 */
if ( ( ( die_rev > > 12 ) & 0xffff ) = = omap_get_jtag_id ( ) )
die_rev = 0 ;
die_rev = ( die_rev > > 17 ) & 0xf ;
if ( die_rev )
return die_rev ;
die_rev = ( omap_readl ( OMAP32_ID_1 ) > > 28 ) & 0xf ;
return die_rev ;
}
void __init omap_check_revision ( void )
{
int i ;
u16 jtag_id ;
u8 die_rev ;
u32 omap_id ;
u8 cpu_type ;
jtag_id = omap_get_jtag_id ( ) ;
die_rev = omap_get_die_rev ( ) ;
omap_id = omap_readl ( OMAP32_ID_0 ) ;
# ifdef DEBUG
2008-12-10 17:36:31 -08:00
printk ( KERN_DEBUG " OMAP_DIE_ID_0: 0x%08x \n " , omap_readl ( OMAP_DIE_ID_0 ) ) ;
printk ( KERN_DEBUG " OMAP_DIE_ID_1: 0x%08x DIE_REV: %i \n " ,
2005-07-10 19:58:12 +01:00
omap_readl ( OMAP_DIE_ID_1 ) ,
( omap_readl ( OMAP_DIE_ID_1 ) > > 17 ) & 0xf ) ;
2008-12-10 17:36:31 -08:00
printk ( KERN_DEBUG " OMAP_PRODUCTION_ID_0: 0x%08x \n " ,
omap_readl ( OMAP_PRODUCTION_ID_0 ) ) ;
printk ( KERN_DEBUG " OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x \n " ,
2005-07-10 19:58:12 +01:00
omap_readl ( OMAP_PRODUCTION_ID_1 ) ,
omap_readl ( OMAP_PRODUCTION_ID_1 ) & 0xffff ) ;
2008-12-10 17:36:31 -08:00
printk ( KERN_DEBUG " OMAP32_ID_0: 0x%08x \n " , omap_readl ( OMAP32_ID_0 ) ) ;
printk ( KERN_DEBUG " OMAP32_ID_1: 0x%08x \n " , omap_readl ( OMAP32_ID_1 ) ) ;
printk ( KERN_DEBUG " JTAG_ID: 0x%04x DIE_REV: %i \n " , jtag_id , die_rev ) ;
2005-07-10 19:58:12 +01:00
# endif
system_serial_high = omap_readl ( OMAP_DIE_ID_0 ) ;
system_serial_low = omap_readl ( OMAP_DIE_ID_1 ) ;
/* First check only the major version in a safe way */
for ( i = 0 ; i < ARRAY_SIZE ( omap_ids ) ; i + + ) {
if ( jtag_id = = ( omap_ids [ i ] . jtag_id ) ) {
2008-12-10 17:36:31 -08:00
omap_revision = omap_ids [ i ] . type ;
2005-07-10 19:58:12 +01:00
break ;
}
}
/* Check if we can find the die revision */
for ( i = 0 ; i < ARRAY_SIZE ( omap_ids ) ; i + + ) {
if ( jtag_id = = omap_ids [ i ] . jtag_id & & die_rev = = omap_ids [ i ] . die_rev ) {
2008-12-10 17:36:31 -08:00
omap_revision = omap_ids [ i ] . type ;
2005-07-10 19:58:12 +01:00
break ;
}
}
/* Finally check also the omap_id */
for ( i = 0 ; i < ARRAY_SIZE ( omap_ids ) ; i + + ) {
if ( jtag_id = = omap_ids [ i ] . jtag_id
& & die_rev = = omap_ids [ i ] . die_rev
& & omap_id = = omap_ids [ i ] . omap_id ) {
2008-12-10 17:36:31 -08:00
omap_revision = omap_ids [ i ] . type ;
2005-07-10 19:58:12 +01:00
break ;
}
}
/* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
2008-12-10 17:36:31 -08:00
cpu_type = omap_revision > > 24 ;
2005-07-10 19:58:12 +01:00
switch ( cpu_type ) {
case 0x07 :
2009-03-23 18:07:39 -07:00
case 0x08 :
2008-12-10 17:36:31 -08:00
omap_revision | = 0x07 ;
2005-07-10 19:58:12 +01:00
break ;
2005-11-10 14:26:48 +00:00
case 0x03 :
2005-07-10 19:58:12 +01:00
case 0x15 :
2008-12-10 17:36:31 -08:00
omap_revision | = 0x15 ;
2005-07-10 19:58:12 +01:00
break ;
case 0x16 :
case 0x17 :
2008-12-10 17:36:31 -08:00
omap_revision | = 0x16 ;
2005-07-10 19:58:12 +01:00
break ;
default :
2008-12-10 17:36:31 -08:00
printk ( KERN_INFO " Unknown OMAP cpu type: 0x%02x \n " , cpu_type ) ;
2005-07-10 19:58:12 +01:00
}
2018-11-19 21:46:41 +02:00
pr_info ( " OMAP%04x " , omap_revision > > 16 ) ;
2008-12-10 17:36:31 -08:00
if ( ( omap_revision > > 8 ) & 0xff )
2018-11-19 21:46:41 +02:00
pr_cont ( " %x " , ( omap_revision > > 8 ) & 0xff ) ;
pr_cont ( " revision %i handled as %02xxx id: %08x%08x \n " ,
2008-12-10 17:36:31 -08:00
die_rev , omap_revision & 0xff , system_serial_low ,
2005-07-10 19:58:12 +01:00
system_serial_high ) ;
}