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 >
*
2011-02-17 20:55:03 +03:00
* Copyright ( C ) 2009 - 11 Texas Instruments
2009-05-29 01:16:04 +04:00
* 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>
2013-09-05 11:29:18 +04:00
# include <linux/random.h>
2013-02-14 15:55:24 +04:00
# include <linux/slab.h>
# ifdef CONFIG_SOC_BUS
# include <linux/sys_soc.h>
# endif
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
2011-11-11 01:45:17 +04:00
# include "common.h"
2006-12-07 04:14:05 +03:00
2012-09-19 21:33:40 +04:00
# include "id.h"
2010-08-02 15:21:41 +04:00
2012-08-31 21:59:07 +04:00
# include "soc.h"
2010-10-08 21:40:20 +04:00
# include "control.h"
2012-11-15 00:10:37 +04:00
# define OMAP4_SILICON_TYPE_STANDARD 0x01
# define OMAP4_SILICON_TYPE_PERFORMANCE 0x02
2013-02-14 15:55:23 +04:00
# define OMAP_SOC_MAX_NAME_LENGTH 16
2008-12-11 04:36:31 +03:00
static unsigned int omap_revision ;
2013-02-14 15:55:23 +04:00
static char soc_name [ OMAP_SOC_MAX_NAME_LENGTH ] ;
static char soc_rev [ OMAP_SOC_MAX_NAME_LENGTH ] ;
2011-07-02 06:30:22 +04:00
u32 omap_features ;
2008-12-11 04:36:31 +03:00
unsigned int omap_rev ( void )
{
return omap_revision ;
}
EXPORT_SYMBOL ( omap_rev ) ;
2008-07-03 13:24:45 +04:00
2009-06-23 14:30:23 +04:00
int omap_type ( void )
{
2015-02-09 17:17:38 +03:00
static u32 val = OMAP2_DEVICETYPE_MASK ;
if ( val < OMAP2_DEVICETYPE_MASK )
return val ;
2009-06-23 14:30:23 +04:00
2015-10-14 08:43:08 +03:00
if ( soc_is_omap24xx ( ) ) {
2009-06-23 14:30:23 +04:00
val = omap_ctrl_readl ( OMAP24XX_CONTROL_STATUS ) ;
2015-10-14 08:43:08 +03:00
} else if ( soc_is_ti81xx ( ) ) {
2015-01-15 04:37:15 +03:00
val = omap_ctrl_readl ( TI81XX_CONTROL_STATUS ) ;
2013-05-27 18:36:33 +04:00
} else if ( soc_is_am33xx ( ) | | soc_is_am43xx ( ) ) {
2012-03-06 04:11:01 +04:00
val = omap_ctrl_readl ( AM33XX_CONTROL_STATUS ) ;
2015-10-14 08:43:08 +03:00
} else if ( soc_is_omap34xx ( ) ) {
2009-06-23 14:30:23 +04:00
val = omap_ctrl_readl ( OMAP343X_CONTROL_STATUS ) ;
2015-10-14 08:43:08 +03:00
} else if ( soc_is_omap44xx ( ) ) {
2010-09-28 00:02:58 +04:00
val = omap_ctrl_readl ( OMAP4_CTRL_MODULE_CORE_STATUS ) ;
2013-02-06 18:55:40 +04:00
} else if ( soc_is_omap54xx ( ) | | soc_is_dra7xx ( ) ) {
2012-04-19 16:12:19 +04:00
val = omap_ctrl_readl ( OMAP5XXX_CONTROL_STATUS ) ;
val & = OMAP5_DEVICETYPE_MASK ;
val > > = 6 ;
goto out ;
2009-11-22 21:11:24 +03:00
} else {
2009-06-23 14:30:23 +04:00
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
2011-03-13 01:50:54 +03:00
# define OMAP_TAP_DIE_ID_44XX_0 0x0200
# define OMAP_TAP_DIE_ID_44XX_1 0x0208
# define OMAP_TAP_DIE_ID_44XX_2 0x020c
# define OMAP_TAP_DIE_ID_44XX_3 0x0210
2014-04-15 21:37:46 +04:00
# define read_tap_reg(reg) readl_relaxed(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
2010-08-02 15:21:41 +04:00
void omap_get_die_id ( struct omap_die_id * odi )
{
2015-10-14 08:43:08 +03:00
if ( soc_is_omap44xx ( ) | | soc_is_omap54xx ( ) | | soc_is_dra7xx ( ) ) {
2011-03-13 01:50:54 +03:00
odi - > id_0 = read_tap_reg ( OMAP_TAP_DIE_ID_44XX_0 ) ;
odi - > id_1 = read_tap_reg ( OMAP_TAP_DIE_ID_44XX_1 ) ;
odi - > id_2 = read_tap_reg ( OMAP_TAP_DIE_ID_44XX_2 ) ;
odi - > id_3 = read_tap_reg ( OMAP_TAP_DIE_ID_44XX_3 ) ;
return ;
}
2010-08-02 15:21:41 +04:00
odi - > id_0 = read_tap_reg ( OMAP_TAP_DIE_ID_0 ) ;
odi - > id_1 = read_tap_reg ( OMAP_TAP_DIE_ID_1 ) ;
odi - > id_2 = read_tap_reg ( OMAP_TAP_DIE_ID_2 ) ;
odi - > id_3 = read_tap_reg ( OMAP_TAP_DIE_ID_3 ) ;
}
2013-09-05 11:29:18 +04:00
static int __init omap_feed_randpool ( void )
{
struct omap_die_id odi ;
/* Throw the die ID into the entropy pool at boot */
omap_get_die_id ( & odi ) ;
add_device_randomness ( & odi , sizeof ( odi ) ) ;
return 0 ;
}
omap_device_initcall ( omap_feed_randpool ) ;
2011-12-19 14:20:15 +04:00
void __init omap2xxx_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 ;
2010-08-02 15:21:41 +04:00
struct omap_die_id odi ;
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 ;
2010-08-02 15:21:41 +04:00
omap_get_die_id ( & odi ) ;
2005-11-10 17:26:51 +03:00
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 ) ;
2010-08-02 15:21:41 +04:00
pr_debug ( " OMAP_TAP_DIE_ID_0: 0x%08x \n " , odi . id_0 ) ;
2008-07-03 13:24:45 +04:00
pr_debug ( " OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i \n " ,
2010-08-02 15:21:41 +04:00
odi . id_1 , ( odi . id_1 > > 28 ) & 0xf ) ;
pr_debug ( " OMAP_TAP_DIE_ID_2: 0x%08x \n " , odi . id_2 ) ;
pr_debug ( " OMAP_TAP_DIE_ID_3: 0x%08x \n " , odi . id_3 ) ;
2008-07-03 13:24:45 +04:00
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 ) ) {
2012-07-26 10:54:26 +04:00
pr_err ( " Unknown OMAP device type. Handling it as OMAP%04x \n " ,
omap_ids [ i ] . type > > 16 ) ;
2005-11-10 17:26:51 +03:00
j = i ;
}
2013-02-14 15:55:23 +04:00
sprintf ( soc_name , " OMAP%04x " , omap_rev ( ) > > 16 ) ;
sprintf ( soc_rev , " ES%x " , ( omap_rev ( ) > > 12 ) & 0xf ) ;
pr_info ( " %s " , soc_name ) ;
2008-12-11 04:36:31 +03:00
if ( ( omap_rev ( ) > > 8 ) & 0x0f )
2013-02-14 15:55:23 +04:00
pr_info ( " %s " , soc_rev ) ;
2008-07-03 13:24:45 +04:00
pr_info ( " \n " ) ;
2008-12-11 04:36:30 +03:00
}
2011-12-19 14:20:14 +04:00
# define OMAP3_SHOW_FEATURE(feat) \
if ( omap3_has_ # # feat ( ) ) \
2016-11-08 00:52:39 +03:00
n + = scnprintf ( buf + n , sizeof ( buf ) - n , # feat " " ) ;
2011-12-19 14:20:14 +04:00
static void __init omap3_cpuinfo ( void )
{
const char * cpu_name ;
2016-11-08 00:52:39 +03:00
char buf [ 64 ] ;
int n = 0 ;
memset ( buf , 0 , sizeof ( buf ) ) ;
2011-12-19 14:20:14 +04:00
/*
* OMAP3430 and OMAP3530 are assumed to be same .
*
* OMAP3525 , OMAP3515 and OMAP3503 can be detected only based
* on available features . Upon detection , update the CPU id
* and CPU class bits .
*/
2015-10-14 08:43:08 +03:00
if ( soc_is_omap3630 ( ) ) {
2017-01-20 19:44:01 +03:00
if ( omap3_has_iva ( ) & & omap3_has_sgx ( ) ) {
cpu_name = ( omap3_has_isp ( ) ) ? " OMAP3630/DM3730 " : " OMAP3621 " ;
} else if ( omap3_has_iva ( ) ) {
cpu_name = " DM3725 " ;
} else if ( omap3_has_sgx ( ) ) {
cpu_name = " OMAP3615/AM3715 " ;
} else {
cpu_name = ( omap3_has_isp ( ) ) ? " AM3703 " : " OMAP3611 " ;
}
2012-05-01 03:37:10 +04:00
} else if ( soc_is_am35xx ( ) ) {
2011-12-19 14:20:14 +04:00
cpu_name = ( omap3_has_sgx ( ) ) ? " AM3517 " : " AM3505 " ;
2015-10-14 08:43:08 +03:00
} else if ( soc_is_ti816x ( ) ) {
2011-12-19 14:20:14 +04:00
cpu_name = " TI816X " ;
2012-07-05 19:05:15 +04:00
} else if ( soc_is_am335x ( ) ) {
2011-12-19 14:20:14 +04:00
cpu_name = " AM335X " ;
2013-05-27 18:36:01 +04:00
} else if ( soc_is_am437x ( ) ) {
cpu_name = " AM437x " ;
2015-10-14 08:43:08 +03:00
} else if ( soc_is_ti814x ( ) ) {
2011-12-19 14:20:14 +04:00
cpu_name = " TI814X " ;
} else if ( omap3_has_iva ( ) & & omap3_has_sgx ( ) ) {
/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
cpu_name = " OMAP3430/3530 " ;
} else if ( omap3_has_iva ( ) ) {
cpu_name = " OMAP3525 " ;
} else if ( omap3_has_sgx ( ) ) {
cpu_name = " OMAP3515 " ;
} else {
cpu_name = " OMAP3503 " ;
}
2016-11-08 00:52:39 +03:00
scnprintf ( soc_name , sizeof ( soc_name ) , " %s " , cpu_name ) ;
2013-02-14 15:55:23 +04:00
2011-12-19 14:20:14 +04:00
/* Print verbose information */
2016-11-08 00:52:39 +03:00
n + = scnprintf ( buf , sizeof ( buf ) - n , " %s %s ( " , soc_name , soc_rev ) ;
2011-12-19 14:20:14 +04:00
OMAP3_SHOW_FEATURE ( l2cache ) ;
OMAP3_SHOW_FEATURE ( iva ) ;
OMAP3_SHOW_FEATURE ( sgx ) ;
OMAP3_SHOW_FEATURE ( neon ) ;
OMAP3_SHOW_FEATURE ( isp ) ;
OMAP3_SHOW_FEATURE ( 192 mhz_clk ) ;
2016-11-08 00:52:39 +03:00
if ( * ( buf + n - 1 ) = = ' ' )
n - - ;
n + = scnprintf ( buf + n , sizeof ( buf ) - n , " ) \n " ) ;
pr_info ( " %s " , buf ) ;
2011-12-19 14:20:14 +04:00
}
2009-11-22 21:10:53 +03:00
# define OMAP3_CHECK_FEATURE(status,feat) \
if ( ( ( status & OMAP3_ # # feat # # _MASK ) \
> > OMAP3_ # # feat # # _SHIFT ) ! = FEAT_ # # feat # # _NONE ) { \
2011-07-02 06:30:22 +04:00
omap_features | = OMAP3_HAS_ # # feat ; \
2009-11-22 21:10:53 +03:00
}
2011-12-19 14:20:15 +04:00
void __init omap3xxx_check_features ( void )
2009-11-22 21:10:53 +03:00
{
u32 status ;
2011-07-02 06:30:22 +04:00
omap_features = 0 ;
2009-11-22 21:10:53 +03:00
status = omap_ctrl_readl ( OMAP3_CONTROL_OMAP_STATUS ) ;
OMAP3_CHECK_FEATURE ( status , L2CACHE ) ;
OMAP3_CHECK_FEATURE ( status , IVA ) ;
OMAP3_CHECK_FEATURE ( status , SGX ) ;
OMAP3_CHECK_FEATURE ( status , NEON ) ;
OMAP3_CHECK_FEATURE ( status , ISP ) ;
2015-10-14 08:43:08 +03:00
if ( soc_is_omap3630 ( ) )
2011-07-02 06:30:22 +04:00
omap_features | = OMAP3_HAS_192MHZ_CLK ;
2015-10-14 08:43:08 +03:00
if ( soc_is_omap3430 ( ) | | soc_is_omap3630 ( ) )
2011-07-02 06:30:22 +04:00
omap_features | = OMAP3_HAS_IO_WAKEUP ;
2015-10-14 08:43:08 +03:00
if ( soc_is_omap3630 ( ) | | omap_rev ( ) = = OMAP3430_REV_ES3_1 | |
ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
The way that we detect which OMAP3 chips support I/O wakeup and
software I/O chain clock control is broken.
Currently, I/O wakeup is marked as present for all OMAP3 SoCs other
than the AM3505/3517. The TI81xx family of SoCs are at present
considered to be OMAP3 SoCs, but don't support I/O wakeup. To resolve
this, convert the existing blacklist approach to an explicit,
whitelist support, in which only SoCs which are known to support I/O
wakeup are listed. (At present, this only includes OMAP34xx,
OMAP3503, OMAP3515, OMAP3525, OMAP3530, and OMAP36xx.)
Also, the current code incorrectly detects the presence of a
software-controllable I/O chain clock on several chips that don't
support it. This results in writes to reserved bitfields, unnecessary
delays, and console messages on kernels running on those chips:
http://www.spinics.net/lists/linux-omap/msg58735.html
Convert this test to a feature test with a chip-by-chip whitelist.
Thanks to Dave Hylands <dhylands@gmail.com> for reporting this problem
and doing some testing to help isolate the cause. Thanks to Steve
Sakoman <sakoman@gmail.com> for catching a bug in the first version of
this patch. Thanks to Russell King <linux@arm.linux.org.uk> for
comments.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
Tested-by: Steve Sakoman <sakoman@gmail.com>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>
Signed-off-by: Kevin Hilman <khilman@ti.com>
2011-10-07 03:18:45 +04:00
omap_rev ( ) = = OMAP3430_REV_ES3_1_2 )
omap_features | = OMAP3_HAS_IO_CHAIN_CTRL ;
2009-11-22 21:10:53 +03:00
2011-07-02 06:30:22 +04:00
omap_features | = OMAP3_HAS_SDRC ;
2011-02-16 19:31:39 +03:00
2012-05-01 03:57:09 +04:00
/*
* am35x fixups :
* - The am35x Chip ID register has bits 12 , 7 : 5 , and 3 : 2 marked as
* reserved and therefore return 0 when read . Unfortunately ,
* OMAP3_CHECK_FEATURE ( ) will interpret some of those zeroes to
* mean that a feature is present even though it isn ' t so clear
* the incorrectly set feature bits .
*/
if ( soc_is_am35xx ( ) )
omap_features & = ~ ( OMAP3_HAS_IVA | OMAP3_HAS_ISP ) ;
2009-11-22 21:10:53 +03:00
/*
* TODO : Get additional info ( where applicable )
* e . g . Size of L2 cache .
*/
2011-12-19 14:20:15 +04:00
omap3_cpuinfo ( ) ;
2009-11-22 21:10:53 +03:00
}
2011-12-19 14:20:15 +04:00
void __init omap4xxx_check_features ( void )
2011-07-02 06:30:22 +04:00
{
u32 si_type ;
2012-11-15 00:10:37 +04:00
si_type =
( read_tap_reg ( OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1 ) > > 16 ) & 0x03 ;
2011-07-02 06:30:22 +04:00
2012-11-15 00:10:37 +04:00
if ( si_type = = OMAP4_SILICON_TYPE_PERFORMANCE )
omap_features = OMAP4_HAS_PERF_SILICON ;
2011-07-02 06:30:22 +04:00
}
2011-12-19 14:20:15 +04:00
void __init ti81xx_check_features ( void )
2011-02-16 19:31:39 +03:00
{
2011-07-02 06:30:22 +04:00
omap_features = OMAP3_HAS_NEON ;
2011-12-19 14:20:15 +04:00
omap3_cpuinfo ( ) ;
2011-02-16 19:31:39 +03:00
}
2013-05-17 14:13:41 +04:00
void __init am33xx_check_features ( void )
{
u32 status ;
omap_features = OMAP3_HAS_NEON ;
status = omap_ctrl_readl ( AM33XX_DEV_FEATURE ) ;
if ( status & AM33XX_SGX_MASK )
omap_features | = OMAP3_HAS_SGX ;
omap3_cpuinfo ( ) ;
}
2011-12-19 14:20:15 +04:00
void __init omap3xxx_check_revision ( void )
2008-12-11 04:36:30 +03:00
{
2013-02-14 15:55:23 +04:00
const char * cpu_rev ;
2008-12-11 04:36:30 +03:00
u32 cpuid , idcode ;
u16 hawkeye ;
u8 rev ;
/*
* 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 .
*/
2013-01-30 20:38:21 +04:00
cpuid = read_cpuid_id ( ) ;
2008-12-11 04:36:30 +03:00
if ( ( ( ( cpuid > > 4 ) & 0xfff ) = = 0xc08 ) & & ( ( cpuid & 0xf ) = = 0x0 ) ) {
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES1_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.0 " ;
2009-11-22 21:10:54 +03:00
return ;
2008-12-11 04:36:30 +03:00
}
/*
* 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
2009-11-22 21:10:56 +03:00
switch ( hawkeye ) {
case 0xb7ae :
/* Handle 34xx/35xx devices */
2008-12-11 04:36:30 +03:00
switch ( rev ) {
2009-11-22 21:10:54 +03:00
case 0 : /* Take care of early samples */
case 1 :
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES2_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 2.0 " ;
2008-12-11 04:36:30 +03:00
break ;
case 2 :
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES2_1 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 2.1 " ;
2008-12-11 04:36:30 +03:00
break ;
case 3 :
2008-12-11 04:36:31 +03:00
omap_revision = OMAP3430_REV_ES3_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 3.0 " ;
2008-12-11 04:36:30 +03:00
break ;
2009-01-29 19:57:16 +03:00
case 4 :
2010-01-20 02:40:26 +03:00
omap_revision = OMAP3430_REV_ES3_1 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 3.1 " ;
2010-01-20 02:40:26 +03:00
break ;
case 7 :
2009-11-22 21:11:24 +03:00
/* FALLTHROUGH */
2008-12-11 04:36:30 +03:00
default :
/* Use the latest known revision as default */
2010-01-20 02:40:26 +03:00
omap_revision = OMAP3430_REV_ES3_1_2 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 3.1.2 " ;
2008-12-11 04:36:30 +03:00
}
2009-11-22 21:10:56 +03:00
break ;
2009-11-22 21:10:58 +03:00
case 0xb868 :
2011-09-14 05:52:13 +04:00
/*
* Handle OMAP / AM 3505 / 3517 devices
2009-11-22 21:10:58 +03:00
*
2011-09-14 05:52:13 +04:00
* Set the device to be OMAP3517 here . Actual device
2009-11-22 21:10:58 +03:00
* is identified later based on the features .
*/
2011-09-14 05:52:14 +04:00
switch ( rev ) {
case 0 :
2012-05-01 03:37:10 +04:00
omap_revision = AM35XX_REV_ES1_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.0 " ;
2011-09-14 05:52:14 +04:00
break ;
case 1 :
/* FALLTHROUGH */
default :
2012-05-01 03:37:10 +04:00
omap_revision = AM35XX_REV_ES1_1 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.1 " ;
2011-09-14 05:52:14 +04:00
}
2009-11-22 21:10:58 +03:00
break ;
2009-11-22 21:11:24 +03:00
case 0xb891 :
2010-08-03 23:59:24 +04:00
/* Handle 36xx devices */
switch ( rev ) {
case 0 : /* Take care of early samples */
omap_revision = OMAP3630_REV_ES1_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.0 " ;
2010-08-03 23:59:24 +04:00
break ;
case 1 :
omap_revision = OMAP3630_REV_ES1_1 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.1 " ;
2010-08-03 23:59:24 +04:00
break ;
case 2 :
2011-09-14 05:52:15 +04:00
/* FALLTHROUGH */
2010-08-03 23:59:24 +04:00
default :
2011-09-14 05:52:15 +04:00
omap_revision = OMAP3630_REV_ES1_2 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.2 " ;
2010-08-03 23:59:24 +04:00
}
2010-08-16 10:21:19 +04:00
break ;
2011-02-16 19:31:39 +03:00
case 0xb81e :
switch ( rev ) {
case 0 :
omap_revision = TI8168_REV_ES1_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.0 " ;
2011-02-16 19:31:39 +03:00
break ;
case 1 :
2011-09-14 05:52:15 +04:00
omap_revision = TI8168_REV_ES1_1 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.1 " ;
2011-09-14 05:52:15 +04:00
break ;
2013-05-30 14:21:01 +04:00
case 2 :
omap_revision = TI8168_REV_ES2_0 ;
cpu_rev = " 2.0 " ;
break ;
case 3 :
/* FALLTHROUGH */
default :
omap_revision = TI8168_REV_ES2_1 ;
cpu_rev = " 2.1 " ;
2011-02-16 19:31:39 +03:00
}
break ;
2011-12-13 22:46:43 +04:00
case 0xb944 :
2013-02-01 14:28:22 +04:00
switch ( rev ) {
case 0 :
omap_revision = AM335X_REV_ES1_0 ;
cpu_rev = " 1.0 " ;
break ;
case 1 :
omap_revision = AM335X_REV_ES2_0 ;
cpu_rev = " 2.0 " ;
break ;
2013-05-09 03:48:02 +04:00
case 2 :
/* FALLTHROUGH */
default :
omap_revision = AM335X_REV_ES2_1 ;
cpu_rev = " 2.1 " ;
break ;
2013-02-01 14:28:22 +04:00
}
2012-01-23 11:56:47 +04:00
break ;
2013-05-27 18:36:01 +04:00
case 0xb98c :
2014-02-07 14:21:24 +04:00
switch ( rev ) {
case 0 :
omap_revision = AM437X_REV_ES1_0 ;
cpu_rev = " 1.0 " ;
break ;
case 1 :
omap_revision = AM437X_REV_ES1_1 ;
cpu_rev = " 1.1 " ;
break ;
2014-11-28 06:32:07 +03:00
case 2 :
/* FALLTHROUGH */
default :
omap_revision = AM437X_REV_ES1_2 ;
cpu_rev = " 1.2 " ;
break ;
2014-02-07 14:21:24 +04:00
}
2013-05-27 18:36:01 +04:00
break ;
2011-12-13 22:46:45 +04:00
case 0xb8f2 :
2015-12-23 02:39:29 +03:00
case 0xb968 :
2011-12-13 22:46:45 +04:00
switch ( rev ) {
case 0 :
/* FALLTHROUGH */
case 1 :
omap_revision = TI8148_REV_ES1_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.0 " ;
2011-12-13 22:46:45 +04:00
break ;
case 2 :
omap_revision = TI8148_REV_ES2_0 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 2.0 " ;
2011-12-13 22:46:45 +04:00
break ;
case 3 :
/* FALLTHROUGH */
default :
omap_revision = TI8148_REV_ES2_1 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 2.1 " ;
2011-12-13 22:46:45 +04:00
break ;
}
2011-12-13 22:46:43 +04:00
break ;
2009-11-22 21:10:56 +03:00
default :
2011-09-14 05:52:15 +04:00
/* Unknown default to latest silicon rev as default */
2011-09-14 05:52:15 +04:00
omap_revision = OMAP3630_REV_ES1_2 ;
2011-12-19 14:20:14 +04:00
cpu_rev = " 1.2 " ;
2015-12-23 02:39:29 +03:00
pr_warn ( " Warning: unknown chip type: hawkeye %04x, assuming OMAP3630ES1.2 \n " ,
hawkeye ) ;
2008-12-11 04:36:30 +03:00
}
2013-02-14 15:55:23 +04:00
sprintf ( soc_rev , " ES%s " , cpu_rev ) ;
2005-11-10 17:26:51 +03:00
}
2011-12-19 14:20:15 +04:00
void __init omap4xxx_check_revision ( void )
2009-12-12 03:16:34 +03:00
{
u32 idcode ;
u16 hawkeye ;
u8 rev ;
/*
* The IC rev detection is done with hawkeye and rev .
* Note that rev does not map directly to defined processor
* revision numbers as ES1 .0 uses value 0.
*/
idcode = read_tap_reg ( OMAP_TAP_IDCODE ) ;
hawkeye = ( idcode > > 12 ) & 0xffff ;
2011-02-17 20:55:03 +03:00
rev = ( idcode > > 28 ) & 0xf ;
2009-12-12 03:16:34 +03:00
2010-09-16 17:14:46 +04:00
/*
2011-07-02 06:30:21 +04:00
* Few initial 4430 ES2 .0 samples IDCODE is same as ES1 .0
2010-09-16 17:14:46 +04:00
* Use ARM register to detect the correct ES version
*/
2011-12-13 22:46:44 +04:00
if ( ! rev & & ( hawkeye ! = 0xb94e ) & & ( hawkeye ! = 0xb975 ) ) {
2013-01-30 20:38:21 +04:00
idcode = read_cpuid_id ( ) ;
2010-09-16 17:14:46 +04:00
rev = ( idcode & 0xf ) - 1 ;
}
switch ( hawkeye ) {
case 0xb852 :
switch ( rev ) {
case 0 :
omap_revision = OMAP4430_REV_ES1_0 ;
break ;
case 1 :
2011-02-17 20:55:03 +03:00
default :
2010-09-16 17:14:46 +04:00
omap_revision = OMAP4430_REV_ES2_0 ;
2011-02-17 20:55:03 +03:00
}
break ;
case 0xb95c :
switch ( rev ) {
case 3 :
omap_revision = OMAP4430_REV_ES2_1 ;
2010-09-16 17:14:46 +04:00
break ;
2011-02-17 20:55:03 +03:00
case 4 :
omap_revision = OMAP4430_REV_ES2_2 ;
2011-12-13 22:46:44 +04:00
break ;
case 6 :
default :
omap_revision = OMAP4430_REV_ES2_3 ;
2011-02-17 20:55:03 +03:00
}
break ;
2011-07-02 06:30:21 +04:00
case 0xb94e :
switch ( rev ) {
case 0 :
omap_revision = OMAP4460_REV_ES1_0 ;
break ;
2012-05-09 20:45:02 +04:00
case 2 :
default :
omap_revision = OMAP4460_REV_ES1_1 ;
break ;
2011-07-02 06:30:21 +04:00
}
break ;
2011-12-13 22:46:44 +04:00
case 0xb975 :
switch ( rev ) {
case 0 :
default :
omap_revision = OMAP4470_REV_ES1_0 ;
break ;
}
break ;
2010-09-16 17:14:46 +04:00
default :
2011-02-17 20:55:03 +03:00
/* Unknown default to latest silicon rev as default */
2011-12-13 22:46:44 +04:00
omap_revision = OMAP4430_REV_ES2_3 ;
2009-12-12 03:16:34 +03:00
}
2013-02-14 15:55:23 +04:00
sprintf ( soc_name , " OMAP%04x " , omap_rev ( ) > > 16 ) ;
sprintf ( soc_rev , " ES%d.%d " , ( omap_rev ( ) > > 12 ) & 0xf ,
( omap_rev ( ) > > 8 ) & 0xf ) ;
pr_info ( " %s %s \n " , soc_name , soc_rev ) ;
2009-12-12 03:16:34 +03:00
}
2012-04-19 16:12:19 +04:00
void __init omap5xxx_check_revision ( void )
{
u32 idcode ;
u16 hawkeye ;
u8 rev ;
idcode = read_tap_reg ( OMAP_TAP_IDCODE ) ;
hawkeye = ( idcode > > 12 ) & 0xffff ;
rev = ( idcode > > 28 ) & 0xff ;
switch ( hawkeye ) {
case 0xb942 :
switch ( rev ) {
case 0 :
2013-09-18 18:05:42 +04:00
/* No support for ES1.0 Test chip */
BUG ( ) ;
2013-01-07 17:59:46 +04:00
case 1 :
default :
omap_revision = OMAP5430_REV_ES2_0 ;
2012-04-19 16:12:19 +04:00
}
break ;
case 0xb998 :
switch ( rev ) {
case 0 :
2013-09-18 18:05:42 +04:00
/* No support for ES1.0 Test chip */
BUG ( ) ;
2013-01-07 17:59:46 +04:00
case 1 :
default :
omap_revision = OMAP5432_REV_ES2_0 ;
2012-04-19 16:12:19 +04:00
}
break ;
default :
/* Unknown default to latest silicon rev as default*/
2013-01-07 17:59:46 +04:00
omap_revision = OMAP5430_REV_ES2_0 ;
2012-04-19 16:12:19 +04:00
}
2013-02-14 15:55:23 +04:00
sprintf ( soc_name , " OMAP%04x " , omap_rev ( ) > > 16 ) ;
sprintf ( soc_rev , " ES%d.0 " , ( omap_rev ( ) > > 12 ) & 0xf ) ;
pr_info ( " %s %s \n " , soc_name , soc_rev ) ;
2012-04-19 16:12:19 +04:00
}
2014-05-19 19:27:11 +04:00
void __init dra7xxx_check_revision ( void )
{
u32 idcode ;
u16 hawkeye ;
u8 rev ;
idcode = read_tap_reg ( OMAP_TAP_IDCODE ) ;
hawkeye = ( idcode > > 12 ) & 0xffff ;
rev = ( idcode > > 28 ) & 0xff ;
switch ( hawkeye ) {
case 0xb990 :
switch ( rev ) {
case 0 :
omap_revision = DRA752_REV_ES1_0 ;
break ;
case 1 :
omap_revision = DRA752_REV_ES1_1 ;
2015-09-01 23:59:25 +03:00
break ;
case 2 :
default :
omap_revision = DRA752_REV_ES2_0 ;
break ;
2014-05-19 19:27:11 +04:00
}
break ;
2014-05-29 23:05:50 +04:00
case 0xb9bc :
switch ( rev ) {
case 0 :
omap_revision = DRA722_REV_ES1_0 ;
break ;
2016-03-09 23:56:31 +03:00
case 1 :
2014-05-29 23:05:50 +04:00
default :
2016-03-09 23:56:31 +03:00
omap_revision = DRA722_REV_ES2_0 ;
2014-05-29 23:05:50 +04:00
break ;
}
break ;
2014-05-19 19:27:11 +04:00
default :
/* Unknown default to latest silicon rev as default*/
2014-08-26 03:15:34 +04:00
pr_warn ( " %s: unknown idcode=0x%08x (hawkeye=0x%08x,rev=0x%x) \n " ,
2014-05-19 19:27:11 +04:00
__func__ , idcode , hawkeye , rev ) ;
2015-09-01 23:59:25 +03:00
omap_revision = DRA752_REV_ES2_0 ;
2014-05-19 19:27:11 +04:00
}
sprintf ( soc_name , " DRA%03x " , omap_rev ( ) > > 16 ) ;
sprintf ( soc_rev , " ES%d.%d " , ( omap_rev ( ) > > 12 ) & 0xf ,
( omap_rev ( ) > > 8 ) & 0xf ) ;
pr_info ( " %s %s \n " , soc_name , soc_rev ) ;
}
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 .
*/
2012-10-30 06:50:21 +04:00
void __init omap2_set_globals_tap ( u32 class , void __iomem * tap )
2008-10-06 16:49:16 +04:00
{
2012-10-30 06:50:21 +04:00
omap_revision = class ;
tap_base = tap ;
2008-10-06 16:49:16 +04:00
2012-10-30 06:50:21 +04:00
/* XXX What is this intended to do? */
2015-10-14 08:43:08 +03:00
if ( soc_is_omap34xx ( ) )
2008-10-06 16:49:16 +04:00
tap_prod_id = 0x0210 ;
else
tap_prod_id = 0x0208 ;
}
2013-02-14 15:55:24 +04:00
# ifdef CONFIG_SOC_BUS
2013-06-06 17:24:38 +04:00
static const char * const omap_types [ ] = {
2013-02-14 15:55:24 +04:00
[ OMAP2_DEVICE_TYPE_TEST ] = " TST " ,
[ OMAP2_DEVICE_TYPE_EMU ] = " EMU " ,
[ OMAP2_DEVICE_TYPE_SEC ] = " HS " ,
[ OMAP2_DEVICE_TYPE_GP ] = " GP " ,
[ OMAP2_DEVICE_TYPE_BAD ] = " BAD " ,
} ;
static const char * __init omap_get_family ( void )
{
2015-10-14 08:43:08 +03:00
if ( soc_is_omap24xx ( ) )
2013-02-14 15:55:24 +04:00
return kasprintf ( GFP_KERNEL , " OMAP2 " ) ;
2015-10-14 08:43:08 +03:00
else if ( soc_is_omap34xx ( ) )
2013-02-14 15:55:24 +04:00
return kasprintf ( GFP_KERNEL , " OMAP3 " ) ;
2015-10-14 08:43:08 +03:00
else if ( soc_is_omap44xx ( ) )
2013-02-14 15:55:24 +04:00
return kasprintf ( GFP_KERNEL , " OMAP4 " ) ;
else if ( soc_is_omap54xx ( ) )
return kasprintf ( GFP_KERNEL , " OMAP5 " ) ;
2015-03-12 02:38:38 +03:00
else if ( soc_is_am33xx ( ) | | soc_is_am335x ( ) )
return kasprintf ( GFP_KERNEL , " AM33xx " ) ;
2014-02-07 14:21:25 +04:00
else if ( soc_is_am43xx ( ) )
return kasprintf ( GFP_KERNEL , " AM43xx " ) ;
2014-05-19 19:27:11 +04:00
else if ( soc_is_dra7xx ( ) )
return kasprintf ( GFP_KERNEL , " DRA7 " ) ;
2013-02-14 15:55:24 +04:00
else
return kasprintf ( GFP_KERNEL , " Unknown " ) ;
}
static ssize_t omap_get_type ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
return sprintf ( buf , " %s \n " , omap_types [ omap_type ( ) ] ) ;
}
static struct device_attribute omap_soc_attr =
__ATTR ( type , S_IRUGO , omap_get_type , NULL ) ;
void __init omap_soc_device_init ( void )
{
struct device * parent ;
struct soc_device * soc_dev ;
struct soc_device_attribute * soc_dev_attr ;
soc_dev_attr = kzalloc ( sizeof ( * soc_dev_attr ) , GFP_KERNEL ) ;
if ( ! soc_dev_attr )
return ;
soc_dev_attr - > machine = soc_name ;
soc_dev_attr - > family = omap_get_family ( ) ;
soc_dev_attr - > revision = soc_rev ;
soc_dev = soc_device_register ( soc_dev_attr ) ;
2013-05-09 19:27:25 +04:00
if ( IS_ERR ( soc_dev ) ) {
2013-02-14 15:55:24 +04:00
kfree ( soc_dev_attr ) ;
return ;
}
parent = soc_device_to_device ( soc_dev ) ;
2013-05-09 19:27:25 +04:00
device_create_file ( parent , & omap_soc_attr ) ;
2013-02-14 15:55:24 +04:00
}
# endif /* CONFIG_SOC_BUS */