2005-07-10 22:58:15 +04:00
/*
* linux / arch / arm / plat - omap / common . c
*
* Code common to all OMAP machines .
2009-05-29 01:16:04 +04:00
* The file is created by Tony Lindgren < tony @ atomide . com >
*
* Copyright ( C ) 2009 Texas Instruments
* Added OMAP4 support - Santosh Shilimkar < santosh . shilimkar @ ti . com >
2005-07-10 22:58:15 +04: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>
# include <linux/delay.h>
# include <linux/console.h>
# include <linux/serial.h>
# include <linux/tty.h>
# include <linux/serial_8250.h>
# include <linux/serial_reg.h>
2006-01-07 19:15:52 +03:00
# include <linux/clk.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2010-05-23 13:18:16 +04:00
# include <linux/omapfb.h>
2005-07-10 22:58:15 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-07-10 22:58:15 +04:00
# include <asm/system.h>
# include <asm/pgtable.h>
# include <asm/mach/map.h>
2005-09-07 20:20:26 +04:00
# include <asm/setup.h>
2005-07-10 22:58:15 +04:00
2009-10-20 20:40:47 +04:00
# include <plat/common.h>
# include <plat/board.h>
# include <plat/control.h>
# include <plat/mux.h>
# include <plat/fpga.h>
2010-02-15 19:48:53 +03:00
# include <plat/serial.h>
2010-05-23 13:18:16 +04:00
# include <plat/vram.h>
2005-07-10 22:58:15 +04:00
2009-10-20 20:40:47 +04:00
# include <plat/clock.h>
2005-07-10 22:58:15 +04:00
2008-03-18 11:04:51 +03:00
# if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
# include ".. / mach-omap2 / sdrc.h"
# endif
2005-07-10 22:58:15 +04:00
# define NO_LENGTH_CHECK 0xffffffff
struct omap_board_config_kernel * omap_board_config ;
2005-09-07 20:20:26 +04:00
int omap_board_config_size ;
2005-07-10 22:58:15 +04:00
static const void * get_config ( u16 tag , size_t len , int skip , size_t * len_out )
{
struct omap_board_config_kernel * kinfo = NULL ;
int i ;
/* Try to find the config from the board-specific structures
* in the kernel . */
for ( i = 0 ; i < omap_board_config_size ; i + + ) {
if ( omap_board_config [ i ] . tag = = tag ) {
2006-12-08 00:58:10 +03:00
if ( skip = = 0 ) {
kinfo = & omap_board_config [ i ] ;
break ;
} else {
skip - - ;
}
2005-07-10 22:58:15 +04:00
}
}
if ( kinfo = = NULL )
return NULL ;
return kinfo - > data ;
}
const void * __omap_get_config ( u16 tag , size_t len , int nr )
{
return get_config ( tag , len , nr , NULL ) ;
}
EXPORT_SYMBOL ( __omap_get_config ) ;
const void * omap_get_var_config ( u16 tag , size_t * len )
{
return get_config ( tag , NO_LENGTH_CHECK , 0 , len ) ;
}
EXPORT_SYMBOL ( omap_get_var_config ) ;
2010-05-23 13:18:16 +04:00
void __init omap_reserve ( void )
{
2010-05-23 02:59:11 +04:00
omapfb_reserve_sdram_memblock ( ) ;
omap_vram_reserve_sdram_memblock ( ) ;
2010-05-23 13:18:16 +04:00
}
2007-03-08 22:32:19 +03:00
/*
* 32 KHz clocksource . . . always available , on pretty most chips except
* OMAP 730 and 1510. Other timers could be used as clocksources , with
* higher resolution in free - running counter modes ( e . g . 12 MHz xtal ) ,
* but systems won ' t necessarily want to spend resources that way .
*/
2009-05-25 22:26:41 +04:00
# define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410
2007-03-08 22:32:19 +03:00
2009-05-25 22:26:41 +04:00
# if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
2007-03-08 22:32:19 +03:00
# include <linux/clocksource.h>
2010-04-07 13:57:22 +04:00
/*
* offset_32k holds the init time counter value . It is then subtracted
* from every counter read to achieve a counter that counts time from the
* kernel boot ( needed for sched_clock ( ) ) .
*/
static u32 offset_32k __read_mostly ;
2009-05-25 22:26:41 +04:00
# ifdef CONFIG_ARCH_OMAP16XX
static cycle_t omap16xx_32k_read ( struct clocksource * cs )
{
2010-04-07 13:57:22 +04:00
return omap_readl ( OMAP16XX_TIMER_32K_SYNCHRONIZED ) - offset_32k ;
2009-05-25 22:26:41 +04:00
}
# else
# define omap16xx_32k_read NULL
# endif
# ifdef CONFIG_ARCH_OMAP2420
static cycle_t omap2420_32k_read ( struct clocksource * cs )
{
2010-04-07 13:57:22 +04:00
return omap_readl ( OMAP2420_32KSYNCT_BASE + 0x10 ) - offset_32k ;
2009-05-25 22:26:41 +04:00
}
# else
# define omap2420_32k_read NULL
# endif
# ifdef CONFIG_ARCH_OMAP2430
static cycle_t omap2430_32k_read ( struct clocksource * cs )
{
2010-04-07 13:57:22 +04:00
return omap_readl ( OMAP2430_32KSYNCT_BASE + 0x10 ) - offset_32k ;
2009-05-25 22:26:41 +04:00
}
# else
# define omap2430_32k_read NULL
# endif
2010-02-12 23:26:48 +03:00
# ifdef CONFIG_ARCH_OMAP3
2009-05-25 22:26:41 +04:00
static cycle_t omap34xx_32k_read ( struct clocksource * cs )
2007-03-08 22:32:19 +03:00
{
2010-04-07 13:57:22 +04:00
return omap_readl ( OMAP3430_32KSYNCT_BASE + 0x10 ) - offset_32k ;
2009-05-25 22:26:41 +04:00
}
# else
# define omap34xx_32k_read NULL
# endif
2009-05-29 01:16:04 +04:00
# ifdef CONFIG_ARCH_OMAP4
static cycle_t omap44xx_32k_read ( struct clocksource * cs )
{
2010-04-07 13:57:22 +04:00
return omap_readl ( OMAP4430_32KSYNCT_BASE + 0x10 ) - offset_32k ;
2009-05-29 01:16:04 +04:00
}
# else
# define omap44xx_32k_read NULL
# endif
2009-05-25 22:26:41 +04:00
/*
* Kernel assumes that sched_clock can be called early but may not have
* things ready yet .
*/
static cycle_t omap_32k_read_dummy ( struct clocksource * cs )
{
return 0 ;
2007-03-08 22:32:19 +03:00
}
static struct clocksource clocksource_32k = {
. name = " 32k_counter " ,
. rating = 250 ,
2009-05-25 22:26:41 +04:00
. read = omap_32k_read_dummy ,
2007-03-08 22:32:19 +03:00
. mask = CLOCKSOURCE_MASK ( 32 ) ,
. shift = 10 ,
. flags = CLOCK_SOURCE_IS_CONTINUOUS ,
} ;
2007-11-13 10:24:03 +03:00
/*
* Returns current time from boot in nsecs . It ' s OK for this to wrap
* around for now , as it ' s just a relative time stamp .
*/
unsigned long long sched_clock ( void )
{
2009-08-14 17:47:28 +04:00
return clocksource_cyc2ns ( clocksource_32k . read ( & clocksource_32k ) ,
clocksource_32k . mult , clocksource_32k . shift ) ;
2007-11-13 10:24:03 +03:00
}
2009-09-25 03:35:48 +04:00
/**
* read_persistent_clock - Return time from a persistent clock .
*
* Reads the time from a source which isn ' t disabled during PM , the
* 32 k sync timer . Convert the cycles elapsed since last read into
* nsecs and adds to a monotonically increasing timespec .
*/
static struct timespec persistent_ts ;
static cycles_t cycles , last_cycles ;
void read_persistent_clock ( struct timespec * ts )
{
unsigned long long nsecs ;
cycles_t delta ;
struct timespec * tsp = & persistent_ts ;
last_cycles = cycles ;
cycles = clocksource_32k . read ( & clocksource_32k ) ;
delta = cycles - last_cycles ;
nsecs = clocksource_cyc2ns ( delta ,
clocksource_32k . mult , clocksource_32k . shift ) ;
timespec_add_ns ( tsp , nsecs ) ;
* ts = * tsp ;
}
2007-03-08 22:32:19 +03:00
static int __init omap_init_clocksource_32k ( void )
{
static char err [ ] __initdata = KERN_ERR
" %s: can't register clocksource! \n " ;
2008-03-18 11:04:51 +03:00
if ( cpu_is_omap16xx ( ) | | cpu_class_is_omap2 ( ) ) {
struct clk * sync_32k_ick ;
2009-05-25 22:26:41 +04:00
if ( cpu_is_omap16xx ( ) )
clocksource_32k . read = omap16xx_32k_read ;
else if ( cpu_is_omap2420 ( ) )
clocksource_32k . read = omap2420_32k_read ;
else if ( cpu_is_omap2430 ( ) )
clocksource_32k . read = omap2430_32k_read ;
else if ( cpu_is_omap34xx ( ) )
clocksource_32k . read = omap34xx_32k_read ;
2009-05-29 01:16:04 +04:00
else if ( cpu_is_omap44xx ( ) )
clocksource_32k . read = omap44xx_32k_read ;
2009-05-25 22:26:41 +04:00
else
return - ENODEV ;
2008-03-18 11:04:51 +03:00
sync_32k_ick = clk_get ( NULL , " omap_32ksync_ick " ) ;
if ( sync_32k_ick )
clk_enable ( sync_32k_ick ) ;
2007-03-08 22:32:19 +03:00
clocksource_32k . mult = clocksource_hz2mult ( 32768 ,
clocksource_32k . shift ) ;
2010-04-07 13:57:22 +04:00
offset_32k = clocksource_32k . read ( & clocksource_32k ) ;
2007-03-08 22:32:19 +03:00
if ( clocksource_register ( & clocksource_32k ) )
printk ( err , clocksource_32k . name ) ;
}
return 0 ;
}
arch_initcall ( omap_init_clocksource_32k ) ;
2009-05-25 22:26:41 +04:00
# endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
2008-03-18 11:04:51 +03:00
/* Global address base setup code */
2008-07-03 13:24:44 +04:00
# if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
2009-05-25 22:26:48 +04:00
static void __init __omap2_set_globals ( struct omap_globals * omap2_globals )
2008-07-03 13:24:44 +04:00
{
2008-10-06 16:49:16 +04:00
omap2_set_globals_tap ( omap2_globals ) ;
2009-01-28 22:27:37 +03:00
omap2_set_globals_sdrc ( omap2_globals ) ;
2008-07-03 13:24:44 +04:00
omap2_set_globals_control ( omap2_globals ) ;
omap2_set_globals_prcm ( omap2_globals ) ;
}
# endif
2008-03-18 11:04:51 +03:00
# if defined(CONFIG_ARCH_OMAP2420)
2008-07-03 13:24:44 +04:00
static struct omap_globals omap242x_globals = {
2008-10-06 16:49:16 +04:00
. class = OMAP242X_CLASS ,
2009-10-20 02:25:31 +04:00
. tap = OMAP2_L4_IO_ADDRESS ( 0x48014000 ) ,
2010-02-15 15:33:37 +03:00
. sdrc = OMAP2420_SDRC_BASE ,
. sms = OMAP2420_SMS_BASE ,
2010-10-08 21:40:17 +04:00
. ctrl = OMAP242X_CTRL_BASE ,
2010-02-15 15:33:37 +03:00
. prm = OMAP2420_PRM_BASE ,
. cm = OMAP2420_CM_BASE ,
2008-07-03 13:24:44 +04:00
} ;
2008-03-18 11:04:51 +03:00
void __init omap2_set_globals_242x ( void )
{
2009-05-25 22:26:48 +04:00
__omap2_set_globals ( & omap242x_globals ) ;
2008-03-18 11:04:51 +03:00
}
# endif
# if defined(CONFIG_ARCH_OMAP2430)
2008-07-03 13:24:44 +04:00
static struct omap_globals omap243x_globals = {
2008-10-06 16:49:16 +04:00
. class = OMAP243X_CLASS ,
2009-10-20 02:25:31 +04:00
. tap = OMAP2_L4_IO_ADDRESS ( 0x4900a000 ) ,
2010-02-15 15:33:37 +03:00
. sdrc = OMAP243X_SDRC_BASE ,
. sms = OMAP243X_SMS_BASE ,
. ctrl = OMAP243X_CTRL_BASE ,
. prm = OMAP2430_PRM_BASE ,
. cm = OMAP2430_CM_BASE ,
2008-07-03 13:24:44 +04:00
} ;
2008-03-18 11:04:51 +03:00
void __init omap2_set_globals_243x ( void )
{
2009-05-25 22:26:48 +04:00
__omap2_set_globals ( & omap243x_globals ) ;
2008-03-18 11:04:51 +03:00
}
# endif
2010-02-15 19:48:53 +03:00
# if defined(CONFIG_ARCH_OMAP3)
2008-07-03 13:24:44 +04:00
2010-02-15 19:48:53 +03:00
static struct omap_globals omap3_globals = {
2008-10-06 16:49:16 +04:00
. class = OMAP343X_CLASS ,
2009-10-20 02:25:31 +04:00
. tap = OMAP2_L4_IO_ADDRESS ( 0x4830A000 ) ,
2010-02-15 15:33:37 +03:00
. sdrc = OMAP343X_SDRC_BASE ,
. sms = OMAP343X_SMS_BASE ,
. ctrl = OMAP343X_CTRL_BASE ,
. prm = OMAP3430_PRM_BASE ,
. cm = OMAP3430_CM_BASE ,
2008-07-03 13:24:44 +04:00
} ;
2010-08-04 15:43:18 +04:00
void __init omap2_set_globals_3xxx ( void )
2008-03-18 11:04:51 +03:00
{
2010-02-15 19:48:53 +03:00
__omap2_set_globals ( & omap3_globals ) ;
}
2010-08-04 15:43:18 +04:00
void __init omap3_map_io ( void )
{
omap2_set_globals_3xxx ( ) ;
omap34xx_map_common_io ( ) ;
}
2008-03-18 11:04:51 +03:00
# endif
2009-05-29 01:16:04 +04:00
# if defined(CONFIG_ARCH_OMAP4)
static struct omap_globals omap4_globals = {
. class = OMAP443X_CLASS ,
2009-12-12 03:16:34 +03:00
. tap = OMAP2_L4_IO_ADDRESS ( OMAP443X_SCM_BASE ) ,
2010-09-28 00:02:58 +04:00
. ctrl = OMAP443X_SCM_BASE ,
2010-09-28 00:02:57 +04:00
. ctrl_pad = OMAP443X_CTRL_BASE ,
2010-02-15 15:33:37 +03:00
. prm = OMAP4430_PRM_BASE ,
. cm = OMAP4430_CM_BASE ,
. cm2 = OMAP4430_CM2_BASE ,
2009-05-29 01:16:04 +04:00
} ;
void __init omap2_set_globals_443x ( void )
{
omap2_set_globals_tap ( & omap4_globals ) ;
omap2_set_globals_control ( & omap4_globals ) ;
2009-12-09 04:24:49 +03:00
omap2_set_globals_prcm ( & omap4_globals ) ;
2009-05-29 01:16:04 +04:00
}
# endif