2019-05-28 10:10:04 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2015-04-29 16:55:57 +02:00
/*
* Copyright ( c ) 2013 - 2015 , NVIDIA CORPORATION . All rights reserved .
*/
# include <linux/device.h>
# include <linux/kernel.h>
# include <linux/bug.h>
# include <soc/tegra/fuse.h>
# include "fuse.h"
# define CPU_PROCESS_CORNERS 2
# define GPU_PROCESS_CORNERS 2
# define SOC_PROCESS_CORNERS 3
# define FUSE_CPU_SPEEDO_0 0x014
# define FUSE_CPU_SPEEDO_1 0x02c
# define FUSE_CPU_SPEEDO_2 0x030
# define FUSE_SOC_SPEEDO_0 0x034
# define FUSE_SOC_SPEEDO_1 0x038
# define FUSE_SOC_SPEEDO_2 0x03c
# define FUSE_CPU_IDDQ 0x018
# define FUSE_SOC_IDDQ 0x040
# define FUSE_GPU_IDDQ 0x128
# define FUSE_FT_REV 0x028
enum {
THRESHOLD_INDEX_0 ,
THRESHOLD_INDEX_1 ,
THRESHOLD_INDEX_COUNT ,
} ;
static const u32 __initconst cpu_process_speedos [ ] [ CPU_PROCESS_CORNERS ] = {
{ 2119 , UINT_MAX } ,
{ 2119 , UINT_MAX } ,
} ;
static const u32 __initconst gpu_process_speedos [ ] [ GPU_PROCESS_CORNERS ] = {
{ UINT_MAX , UINT_MAX } ,
{ UINT_MAX , UINT_MAX } ,
} ;
static const u32 __initconst soc_process_speedos [ ] [ SOC_PROCESS_CORNERS ] = {
{ 1950 , 2100 , UINT_MAX } ,
{ 1950 , 2100 , UINT_MAX } ,
} ;
static u8 __init get_speedo_revision ( void )
{
return tegra_fuse_read_spare ( 4 ) < < 2 |
tegra_fuse_read_spare ( 3 ) < < 1 |
tegra_fuse_read_spare ( 2 ) < < 0 ;
}
static void __init rev_sku_to_speedo_ids ( struct tegra_sku_info * sku_info ,
u8 speedo_rev , int * threshold )
{
int sku = sku_info - > sku_id ;
/* Assign to default */
sku_info - > cpu_speedo_id = 0 ;
sku_info - > soc_speedo_id = 0 ;
sku_info - > gpu_speedo_id = 0 ;
* threshold = THRESHOLD_INDEX_0 ;
switch ( sku ) {
case 0x00 : /* Engineering SKU */
case 0x01 : /* Engineering SKU */
case 0x07 :
case 0x17 :
case 0x27 :
if ( speedo_rev > = 2 )
sku_info - > gpu_speedo_id = 1 ;
break ;
case 0x13 :
if ( speedo_rev > = 2 )
sku_info - > gpu_speedo_id = 1 ;
sku_info - > cpu_speedo_id = 1 ;
break ;
default :
pr_err ( " Tegra210: unknown SKU %#04x \n " , sku ) ;
/* Using the default for the error case */
break ;
}
}
static int get_process_id ( int value , const u32 * speedos , unsigned int num )
{
unsigned int i ;
for ( i = 0 ; i < num ; i + + )
2020-11-18 20:44:57 -08:00
if ( value < speedos [ i ] )
2015-04-29 16:55:57 +02:00
return i ;
return - EINVAL ;
}
void __init tegra210_init_speedo_data ( struct tegra_sku_info * sku_info )
{
2020-11-03 15:28:37 +00:00
int cpu_speedo [ 3 ] , soc_speedo [ 3 ] ;
2015-04-29 16:55:57 +02:00
unsigned int index ;
u8 speedo_revision ;
BUILD_BUG_ON ( ARRAY_SIZE ( cpu_process_speedos ) ! =
THRESHOLD_INDEX_COUNT ) ;
BUILD_BUG_ON ( ARRAY_SIZE ( gpu_process_speedos ) ! =
THRESHOLD_INDEX_COUNT ) ;
BUILD_BUG_ON ( ARRAY_SIZE ( soc_process_speedos ) ! =
THRESHOLD_INDEX_COUNT ) ;
/* Read speedo/IDDQ fuses */
cpu_speedo [ 0 ] = tegra_fuse_read_early ( FUSE_CPU_SPEEDO_0 ) ;
cpu_speedo [ 1 ] = tegra_fuse_read_early ( FUSE_CPU_SPEEDO_1 ) ;
cpu_speedo [ 2 ] = tegra_fuse_read_early ( FUSE_CPU_SPEEDO_2 ) ;
soc_speedo [ 0 ] = tegra_fuse_read_early ( FUSE_SOC_SPEEDO_0 ) ;
soc_speedo [ 1 ] = tegra_fuse_read_early ( FUSE_SOC_SPEEDO_1 ) ;
2019-01-04 15:16:46 +08:00
soc_speedo [ 2 ] = tegra_fuse_read_early ( FUSE_SOC_SPEEDO_2 ) ;
2015-04-29 16:55:57 +02:00
/*
* Determine CPU , GPU and SoC speedo values depending on speedo fusing
* revision . Note that GPU speedo value is fused in CPU_SPEEDO_2 .
*/
speedo_revision = get_speedo_revision ( ) ;
pr_info ( " Speedo Revision %u \n " , speedo_revision ) ;
if ( speedo_revision > = 3 ) {
sku_info - > cpu_speedo_value = cpu_speedo [ 0 ] ;
sku_info - > gpu_speedo_value = cpu_speedo [ 2 ] ;
sku_info - > soc_speedo_value = soc_speedo [ 0 ] ;
} else if ( speedo_revision = = 2 ) {
sku_info - > cpu_speedo_value = ( - 1938 + ( 1095 * cpu_speedo [ 0 ] / 100 ) ) / 10 ;
sku_info - > gpu_speedo_value = ( - 1662 + ( 1082 * cpu_speedo [ 2 ] / 100 ) ) / 10 ;
sku_info - > soc_speedo_value = ( - 705 + ( 1037 * soc_speedo [ 0 ] / 100 ) ) / 10 ;
} else {
sku_info - > cpu_speedo_value = 2100 ;
sku_info - > gpu_speedo_value = cpu_speedo [ 2 ] - 75 ;
sku_info - > soc_speedo_value = 1900 ;
}
if ( ( sku_info - > cpu_speedo_value < = 0 ) | |
( sku_info - > gpu_speedo_value < = 0 ) | |
( sku_info - > soc_speedo_value < = 0 ) ) {
WARN ( 1 , " speedo value not fused \n " ) ;
return ;
}
rev_sku_to_speedo_ids ( sku_info , speedo_revision , & index ) ;
sku_info - > gpu_process_id = get_process_id ( sku_info - > gpu_speedo_value ,
gpu_process_speedos [ index ] ,
GPU_PROCESS_CORNERS ) ;
sku_info - > cpu_process_id = get_process_id ( sku_info - > cpu_speedo_value ,
cpu_process_speedos [ index ] ,
CPU_PROCESS_CORNERS ) ;
sku_info - > soc_process_id = get_process_id ( sku_info - > soc_speedo_value ,
soc_process_speedos [ index ] ,
SOC_PROCESS_CORNERS ) ;
pr_debug ( " Tegra GPU Speedo ID=%d, Speedo Value=%d \n " ,
sku_info - > gpu_speedo_id , sku_info - > gpu_speedo_value ) ;
}