2007-02-11 20:31:01 +03:00
/* linux/arch/arm/plat-s3c24xx/cpu.c
2005-04-17 02:20:36 +04:00
*
* Copyright ( c ) 2004 - 2005 Simtec Electronics
* http : //www.simtec.co.uk/products/SWLINUX/
* Ben Dooks < ben @ simtec . co . uk >
*
* S3C24XX CPU Support
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/ioport.h>
2006-12-18 01:22:26 +03:00
# include <linux/serial_core.h>
2005-10-29 22:07:23 +04:00
# include <linux/platform_device.h>
2008-04-16 03:15:20 +04:00
# include <linux/delay.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2005-04-17 02:20:36 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/irq.h>
2008-04-16 03:15:20 +04:00
# include <asm/cacheflush.h>
2005-04-17 02:20:36 +04:00
# include <asm/mach/arch.h>
# include <asm/mach/map.h>
2008-08-05 19:14:15 +04:00
# include <mach/system-reset.h>
2008-04-16 03:15:20 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/regs-gpio.h>
2008-10-08 01:26:09 +04:00
# include <plat/regs-serial.h>
2005-04-17 02:20:36 +04:00
2008-10-08 01:26:09 +04:00
# include <plat/cpu.h>
# include <plat/devs.h>
2008-10-08 02:09:51 +04:00
# include <plat/clock.h>
2008-10-08 01:26:09 +04:00
# include <plat/s3c2400.h>
# include <plat/s3c2410.h>
2008-10-08 02:09:51 +04:00
# include <plat/s3c2412.h>
2010-04-28 13:09:01 +04:00
# include <plat/s3c2416.h>
2010-01-26 10:47:41 +03:00
# include <plat/s3c244x.h>
2008-10-08 01:26:09 +04:00
# include <plat/s3c2443.h>
2005-04-17 02:20:36 +04:00
/* table of supported CPUs */
2006-02-02 00:24:24 +03:00
static const char name_s3c2400 [ ] = " S3C2400 " ;
2005-04-17 02:20:36 +04:00
static const char name_s3c2410 [ ] = " S3C2410 " ;
2006-06-25 00:21:27 +04:00
static const char name_s3c2412 [ ] = " S3C2412 " ;
2010-04-28 13:09:01 +04:00
static const char name_s3c2416 [ ] = " S3C2416 " ;
2005-04-17 02:20:36 +04:00
static const char name_s3c2440 [ ] = " S3C2440 " ;
2006-06-19 02:06:41 +04:00
static const char name_s3c2442 [ ] = " S3C2442 " ;
2009-09-23 00:40:39 +04:00
static const char name_s3c2442b [ ] = " S3C2442B " ;
2007-02-16 14:12:31 +03:00
static const char name_s3c2443 [ ] = " S3C2443 " ;
2005-04-17 02:20:36 +04:00
static const char name_s3c2410a [ ] = " S3C2410A " ;
static const char name_s3c2440a [ ] = " S3C2440A " ;
static struct cpu_table cpu_ids [ ] __initdata = {
{
. idcode = 0x32410000 ,
. idmask = 0xffffffff ,
. map_io = s3c2410_map_io ,
. init_clocks = s3c2410_init_clocks ,
. init_uarts = s3c2410_init_uarts ,
. init = s3c2410_init ,
. name = name_s3c2410
} ,
{
. idcode = 0x32410002 ,
. idmask = 0xffffffff ,
. map_io = s3c2410_map_io ,
. init_clocks = s3c2410_init_clocks ,
. init_uarts = s3c2410_init_uarts ,
2009-07-31 02:23:38 +04:00
. init = s3c2410a_init ,
2005-04-17 02:20:36 +04:00
. name = name_s3c2410a
} ,
{
. idcode = 0x32440000 ,
. idmask = 0xffffffff ,
2006-06-19 02:06:41 +04:00
. map_io = s3c244x_map_io ,
. init_clocks = s3c244x_init_clocks ,
. init_uarts = s3c244x_init_uarts ,
2005-04-17 02:20:36 +04:00
. init = s3c2440_init ,
. name = name_s3c2440
} ,
{
. idcode = 0x32440001 ,
. idmask = 0xffffffff ,
2006-06-19 02:06:41 +04:00
. map_io = s3c244x_map_io ,
. init_clocks = s3c244x_init_clocks ,
. init_uarts = s3c244x_init_uarts ,
2005-04-17 02:20:36 +04:00
. init = s3c2440_init ,
. name = name_s3c2440a
2006-02-02 00:24:24 +03:00
} ,
2006-06-19 02:06:41 +04:00
{
. idcode = 0x32440aaa ,
. idmask = 0xffffffff ,
. map_io = s3c244x_map_io ,
. init_clocks = s3c244x_init_clocks ,
. init_uarts = s3c244x_init_uarts ,
. init = s3c2442_init ,
. name = name_s3c2442
} ,
2009-09-23 00:40:39 +04:00
{
. idcode = 0x32440aab ,
. idmask = 0xffffffff ,
. map_io = s3c244x_map_io ,
. init_clocks = s3c244x_init_clocks ,
. init_uarts = s3c244x_init_uarts ,
. init = s3c2442_init ,
. name = name_s3c2442b
} ,
2006-06-25 00:21:27 +04:00
{
. idcode = 0x32412001 ,
. idmask = 0xffffffff ,
. map_io = s3c2412_map_io ,
. init_clocks = s3c2412_init_clocks ,
. init_uarts = s3c2412_init_uarts ,
. init = s3c2412_init ,
. name = name_s3c2412 ,
} ,
2006-09-20 23:39:15 +04:00
{ /* a newer version of the s3c2412 */
. idcode = 0x32412003 ,
. idmask = 0xffffffff ,
. map_io = s3c2412_map_io ,
. init_clocks = s3c2412_init_clocks ,
. init_uarts = s3c2412_init_uarts ,
. init = s3c2412_init ,
. name = name_s3c2412 ,
} ,
2010-04-28 13:09:01 +04:00
{ /* a strange version of the s3c2416 */
. idcode = 0x32450003 ,
. idmask = 0xffffffff ,
. map_io = s3c2416_map_io ,
. init_clocks = s3c2416_init_clocks ,
. init_uarts = s3c2416_init_uarts ,
. init = s3c2416_init ,
. name = name_s3c2416 ,
} ,
2007-02-16 14:12:31 +03:00
{
. idcode = 0x32443001 ,
. idmask = 0xffffffff ,
. map_io = s3c2443_map_io ,
. init_clocks = s3c2443_init_clocks ,
. init_uarts = s3c2443_init_uarts ,
. init = s3c2443_init ,
. name = name_s3c2443 ,
} ,
2006-02-02 00:24:24 +03:00
{
. idcode = 0x0 , /* S3C2400 doesn't have an idcode */
. idmask = 0xffffffff ,
. map_io = s3c2400_map_io ,
. init_clocks = s3c2400_init_clocks ,
. init_uarts = s3c2400_init_uarts ,
. init = s3c2400_init ,
. name = name_s3c2400
} ,
2005-04-17 02:20:36 +04:00
} ;
/* minimal IO mapping */
static struct map_desc s3c_iodesc [ ] __initdata = {
IODESC_ENT ( GPIO ) ,
IODESC_ENT ( IRQ ) ,
IODESC_ENT ( MEMCTRL ) ,
IODESC_ENT ( UART )
} ;
2008-10-21 17:06:31 +04:00
/* read cpu identificaiton code */
2005-04-17 02:20:36 +04:00
2006-06-25 00:21:27 +04:00
static unsigned long s3c24xx_read_idcode_v5 ( void )
{
2010-04-28 13:00:07 +04:00
# if defined(CONFIG_CPU_S3C2416)
/* s3c2416 is v5, with S3C24XX_GSTATUS1 instead of S3C2412_GSTATUS1 */
u32 gs = __raw_readl ( S3C24XX_GSTATUS1 ) ;
/* test for s3c2416 or similar device */
if ( ( gs > > 16 ) = = 0x3245 )
return gs ;
# endif
2006-06-25 00:21:27 +04:00
# if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
return __raw_readl ( S3C2412_GSTATUS1 ) ;
# else
return 1UL ; /* don't look like an 2400 */
# endif
}
static unsigned long s3c24xx_read_idcode_v4 ( void )
{
# ifndef CONFIG_CPU_S3C2400
return __raw_readl ( S3C2410_GSTATUS1 ) ;
# else
return 0UL ;
# endif
}
2008-04-16 03:15:20 +04:00
/* Hook for arm_pm_restart to ensure we execute the reset code
* with the caches enabled . It seems at least the S3C2440 has a problem
* resetting if there is bus activity interrupted by the reset .
*/
2009-03-19 19:20:24 +03:00
static void s3c24xx_pm_restart ( char mode , const char * cmd )
2008-04-16 03:15:20 +04:00
{
if ( mode ! = ' s ' ) {
unsigned long flags ;
local_irq_save ( flags ) ;
__cpuc_flush_kern_all ( ) ;
__cpuc_flush_user_all ( ) ;
2009-03-19 19:20:24 +03:00
arch_reset ( mode , cmd ) ;
2008-04-16 03:15:20 +04:00
local_irq_restore ( flags ) ;
}
/* fallback, or unhandled */
2009-03-19 19:20:24 +03:00
arm_machine_restart ( mode , cmd ) ;
2008-04-16 03:15:20 +04:00
}
2005-04-17 02:20:36 +04:00
void __init s3c24xx_init_io ( struct map_desc * mach_desc , int size )
{
2006-02-02 00:24:24 +03:00
unsigned long idcode = 0x0 ;
2005-04-17 02:20:36 +04:00
/* initialise the io descriptors we need for initialisation */
2008-10-21 17:06:31 +04:00
iotable_init ( mach_desc , size ) ;
2005-04-17 02:20:36 +04:00
iotable_init ( s3c_iodesc , ARRAY_SIZE ( s3c_iodesc ) ) ;
2006-06-25 00:21:27 +04:00
if ( cpu_architecture ( ) > = CPU_ARCH_ARMv5 ) {
idcode = s3c24xx_read_idcode_v5 ( ) ;
} else {
idcode = s3c24xx_read_idcode_v4 ( ) ;
}
2006-02-02 00:24:24 +03:00
2008-04-16 03:15:20 +04:00
arm_pm_restart = s3c24xx_pm_restart ;
2008-10-21 17:06:31 +04:00
s3c_init_cpu ( idcode , cpu_ids , ARRAY_SIZE ( cpu_ids ) ) ;
2006-06-19 02:04:05 +04:00
}