2020-09-06 22:29:31 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Support for Ingenic SoCs
*
* Copyright ( C ) 2009 - 2010 , Lars - Peter Clausen < lars @ metafoo . de >
* Copyright ( C ) 2011 , Maarten ter Huurne < maarten @ treewalker . org >
* Copyright ( C ) 2020 Paul Cercueil < paul @ crapouillou . net >
*/
2021-08-23 20:34:05 +03:00
# include <linux/clk.h>
# include <linux/of.h>
2020-09-06 22:29:31 +03:00
# include <linux/of_address.h>
# include <linux/of_fdt.h>
# include <linux/pm.h>
# include <linux/sizes.h>
# include <linux/suspend.h>
# include <linux/types.h>
# include <asm/bootinfo.h>
2023-06-04 15:26:54 +03:00
# include <asm/io.h>
2020-09-06 22:29:31 +03:00
# include <asm/machine.h>
# include <asm/reboot.h>
static __init char * ingenic_get_system_type ( unsigned long machtype )
{
switch ( machtype ) {
MIPS: Ingenic: Add system type for new Ingenic SoCs.
Add JZ4730, JZ4750, JZ4755, JZ4760, JZ4760B, X2000H, and X2100 system
type for cat /proc/cpuinfo to give out JZ4730, JZ4750, JZ4755, JZ4760,
JZ4760B, X2000H, and X2100.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2021-07-15 19:57:07 +03:00
case MACH_INGENIC_X2100 :
return " X2100 " ;
case MACH_INGENIC_X2000H :
return " X2000H " ;
2020-09-22 04:24:43 +03:00
case MACH_INGENIC_X2000E :
return " X2000E " ;
case MACH_INGENIC_X2000 :
return " X2000 " ;
2020-09-06 22:29:31 +03:00
case MACH_INGENIC_X1830 :
return " X1830 " ;
2020-09-22 04:24:43 +03:00
case MACH_INGENIC_X1000E :
return " X1000E " ;
2020-09-06 22:29:31 +03:00
case MACH_INGENIC_X1000 :
return " X1000 " ;
case MACH_INGENIC_JZ4780 :
return " JZ4780 " ;
2020-09-22 04:24:43 +03:00
case MACH_INGENIC_JZ4775 :
return " JZ4775 " ;
2020-09-06 22:29:31 +03:00
case MACH_INGENIC_JZ4770 :
return " JZ4770 " ;
MIPS: Ingenic: Add system type for new Ingenic SoCs.
Add JZ4730, JZ4750, JZ4755, JZ4760, JZ4760B, X2000H, and X2100 system
type for cat /proc/cpuinfo to give out JZ4730, JZ4750, JZ4755, JZ4760,
JZ4760B, X2000H, and X2100.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2021-07-15 19:57:07 +03:00
case MACH_INGENIC_JZ4760B :
return " JZ4760B " ;
case MACH_INGENIC_JZ4760 :
return " JZ4760 " ;
case MACH_INGENIC_JZ4755 :
return " JZ4755 " ;
case MACH_INGENIC_JZ4750 :
return " JZ4750 " ;
2020-09-06 22:29:31 +03:00
case MACH_INGENIC_JZ4725B :
return " JZ4725B " ;
MIPS: Ingenic: Add system type for new Ingenic SoCs.
Add JZ4730, JZ4750, JZ4755, JZ4760, JZ4760B, X2000H, and X2100 system
type for cat /proc/cpuinfo to give out JZ4730, JZ4750, JZ4755, JZ4760,
JZ4760B, X2000H, and X2100.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2021-07-15 19:57:07 +03:00
case MACH_INGENIC_JZ4730 :
return " JZ4730 " ;
2020-09-06 22:29:31 +03:00
default :
return " JZ4740 " ;
}
}
2023-06-04 15:26:54 +03:00
# define INGENIC_CGU_BASE 0x10000000
# define JZ4750_CGU_CPCCR_ECS BIT(30)
# define JZ4760_CGU_CPCCR_ECS BIT(31)
static __init void ingenic_force_12M_ext ( const void * fdt , unsigned int mask )
{
const __be32 * prop ;
unsigned int cpccr ;
void __iomem * cgu ;
bool use_div ;
int offset ;
offset = fdt_path_offset ( fdt , " /ext " ) ;
if ( offset < 0 )
return ;
prop = fdt_getprop ( fdt , offset , " clock-frequency " , NULL ) ;
if ( ! prop )
return ;
/*
* If the external oscillator is 24 MHz , enable the / 2 divider to
* drive it down to 12 MHz , since this is what the hardware can work
* with .
* The 16 MHz cutoff value is arbitrary ; setting it to 12 MHz would not
* work as the crystal frequency ( as reported in the Device Tree ) might
* be slightly above this value .
*/
use_div = be32_to_cpup ( prop ) > = 16000000 ;
cgu = ioremap ( INGENIC_CGU_BASE , 0x4 ) ;
if ( ! cgu )
return ;
cpccr = ioread32 ( cgu ) ;
if ( use_div )
cpccr | = mask ;
else
cpccr & = ~ mask ;
iowrite32 ( cpccr , cgu ) ;
iounmap ( cgu ) ;
}
2020-09-06 22:29:31 +03:00
static __init const void * ingenic_fixup_fdt ( const void * fdt , const void * match_data )
{
/*
* Old devicetree files for the qi , lb60 board did not have a / memory
* node . Hardcode the memory info here .
*/
if ( ! fdt_node_check_compatible ( fdt , 0 , " qi,lb60 " ) & &
fdt_path_offset ( fdt , " /memory " ) < 0 )
early_init_dt_add_memory_arch ( 0 , SZ_32M ) ;
mips_machtype = ( unsigned long ) match_data ;
system_type = ingenic_get_system_type ( mips_machtype ) ;
2023-06-04 15:26:54 +03:00
switch ( mips_machtype ) {
case MACH_INGENIC_JZ4750 :
case MACH_INGENIC_JZ4755 :
ingenic_force_12M_ext ( fdt , JZ4750_CGU_CPCCR_ECS ) ;
break ;
case MACH_INGENIC_JZ4760 :
ingenic_force_12M_ext ( fdt , JZ4760_CGU_CPCCR_ECS ) ;
break ;
default :
break ;
}
2020-09-06 22:29:31 +03:00
return fdt ;
}
static const struct of_device_id ingenic_of_match [ ] __initconst = {
MIPS: Ingenic: Add system type for new Ingenic SoCs.
Add JZ4730, JZ4750, JZ4755, JZ4760, JZ4760B, X2000H, and X2100 system
type for cat /proc/cpuinfo to give out JZ4730, JZ4750, JZ4755, JZ4760,
JZ4760B, X2000H, and X2100.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2021-07-15 19:57:07 +03:00
{ . compatible = " ingenic,jz4730 " , . data = ( void * ) MACH_INGENIC_JZ4730 } ,
2020-09-06 22:29:31 +03:00
{ . compatible = " ingenic,jz4740 " , . data = ( void * ) MACH_INGENIC_JZ4740 } ,
{ . compatible = " ingenic,jz4725b " , . data = ( void * ) MACH_INGENIC_JZ4725B } ,
MIPS: Ingenic: Add system type for new Ingenic SoCs.
Add JZ4730, JZ4750, JZ4755, JZ4760, JZ4760B, X2000H, and X2100 system
type for cat /proc/cpuinfo to give out JZ4730, JZ4750, JZ4755, JZ4760,
JZ4760B, X2000H, and X2100.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2021-07-15 19:57:07 +03:00
{ . compatible = " ingenic,jz4750 " , . data = ( void * ) MACH_INGENIC_JZ4750 } ,
{ . compatible = " ingenic,jz4755 " , . data = ( void * ) MACH_INGENIC_JZ4755 } ,
{ . compatible = " ingenic,jz4760 " , . data = ( void * ) MACH_INGENIC_JZ4760 } ,
{ . compatible = " ingenic,jz4760b " , . data = ( void * ) MACH_INGENIC_JZ4760B } ,
2020-09-06 22:29:31 +03:00
{ . compatible = " ingenic,jz4770 " , . data = ( void * ) MACH_INGENIC_JZ4770 } ,
2020-09-22 04:24:43 +03:00
{ . compatible = " ingenic,jz4775 " , . data = ( void * ) MACH_INGENIC_JZ4775 } ,
2020-09-06 22:29:31 +03:00
{ . compatible = " ingenic,jz4780 " , . data = ( void * ) MACH_INGENIC_JZ4780 } ,
{ . compatible = " ingenic,x1000 " , . data = ( void * ) MACH_INGENIC_X1000 } ,
2020-09-22 04:24:43 +03:00
{ . compatible = " ingenic,x1000e " , . data = ( void * ) MACH_INGENIC_X1000E } ,
2020-09-06 22:29:31 +03:00
{ . compatible = " ingenic,x1830 " , . data = ( void * ) MACH_INGENIC_X1830 } ,
2020-09-22 04:24:43 +03:00
{ . compatible = " ingenic,x2000 " , . data = ( void * ) MACH_INGENIC_X2000 } ,
{ . compatible = " ingenic,x2000e " , . data = ( void * ) MACH_INGENIC_X2000E } ,
MIPS: Ingenic: Add system type for new Ingenic SoCs.
Add JZ4730, JZ4750, JZ4755, JZ4760, JZ4760B, X2000H, and X2100 system
type for cat /proc/cpuinfo to give out JZ4730, JZ4750, JZ4755, JZ4760,
JZ4760B, X2000H, and X2100.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2021-07-15 19:57:07 +03:00
{ . compatible = " ingenic,x2000h " , . data = ( void * ) MACH_INGENIC_X2000H } ,
{ . compatible = " ingenic,x2100 " , . data = ( void * ) MACH_INGENIC_X2100 } ,
2020-09-06 22:29:31 +03:00
{ }
} ;
MIPS_MACHINE ( ingenic ) = {
. matches = ingenic_of_match ,
. fixup_fdt = ingenic_fixup_fdt ,
} ;
static void ingenic_wait_instr ( void )
{
__asm__ ( " .set push; \n "
" .set mips3; \n "
" wait; \n "
" .set pop; \n "
) ;
}
static void ingenic_halt ( void )
{
for ( ; ; )
ingenic_wait_instr ( ) ;
}
2023-06-04 15:26:53 +03:00
static int ingenic_pm_enter ( suspend_state_t state )
2020-09-06 22:29:31 +03:00
{
ingenic_wait_instr ( ) ;
return 0 ;
}
2023-06-04 15:26:53 +03:00
static const struct platform_suspend_ops ingenic_pm_ops = {
2020-09-06 22:29:31 +03:00
. valid = suspend_valid_only_mem ,
. enter = ingenic_pm_enter ,
} ;
static int __init ingenic_pm_init ( void )
{
if ( boot_cpu_type ( ) = = CPU_XBURST ) {
if ( IS_ENABLED ( CONFIG_PM_SLEEP ) )
suspend_set_ops ( & ingenic_pm_ops ) ;
_machine_halt = ingenic_halt ;
}
return 0 ;
}
late_initcall ( ingenic_pm_init ) ;