2005-04-17 02:20:36 +04:00
/*
* linux / arch / arm / mach - integrator / core . c
*
* Copyright ( C ) 2000 - 2003 Deep Blue Solutions Ltd
*
* 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/types.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/device.h>
# include <linux/spinlock.h>
# include <linux/interrupt.h>
2006-07-02 01:32:32 +04:00
# include <linux/irq.h>
2010-05-22 22:47:18 +04:00
# include <linux/memblock.h>
2005-04-17 02:20:36 +04:00
# include <linux/sched.h>
2005-06-18 13:15:46 +04:00
# include <linux/smp.h>
2006-03-27 02:13:39 +04:00
# include <linux/termios.h>
2006-01-07 16:52:45 +03:00
# include <linux/amba/bus.h>
2006-03-27 02:13:39 +04:00
# include <linux/amba/serial.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2010-11-17 12:04:33 +03:00
# include <linux/clkdev.h>
2005-04-17 02:20:36 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2010-01-14 22:59:37 +03:00
# include <mach/platform.h>
2008-08-05 19:14:15 +04:00
# include <mach/cm.h>
2012-02-26 13:46:48 +04:00
# include <mach/irqs.h>
2005-04-17 02:20:36 +04:00
# include <asm/leds.h>
2011-12-20 14:55:19 +04:00
# include <asm/mach-types.h>
2005-04-17 02:20:36 +04:00
# include <asm/mach/time.h>
2010-05-22 21:18:57 +04:00
# include <asm/pgtable.h>
2005-04-17 02:20:36 +04:00
2006-03-27 02:13:39 +04:00
static struct amba_pl010_data integrator_uart_data ;
2011-12-18 18:50:51 +04:00
# define INTEGRATOR_RTC_IRQ { IRQ_RTCINT }
# define INTEGRATOR_UART0_IRQ { IRQ_UARTINT0 }
# define INTEGRATOR_UART1_IRQ { IRQ_UARTINT1 }
# define KMI0_IRQ { IRQ_KMIINT0 }
# define KMI1_IRQ { IRQ_KMIINT1 }
2005-04-17 02:20:36 +04:00
2012-06-11 02:14:15 +04:00
static AMBA_APB_DEVICE ( rtc , " rtc " , 0 ,
2011-12-18 18:50:51 +04:00
INTEGRATOR_RTC_BASE , INTEGRATOR_RTC_IRQ , NULL ) ;
2005-04-17 02:20:36 +04:00
2012-06-11 02:14:15 +04:00
static AMBA_APB_DEVICE ( uart0 , " uart0 " , 0 ,
2011-12-18 18:50:51 +04:00
INTEGRATOR_UART0_BASE , INTEGRATOR_UART0_IRQ , & integrator_uart_data ) ;
2005-04-17 02:20:36 +04:00
2012-06-11 02:14:15 +04:00
static AMBA_APB_DEVICE ( uart1 , " uart1 " , 0 ,
2011-12-18 18:50:51 +04:00
INTEGRATOR_UART1_BASE , INTEGRATOR_UART1_IRQ , & integrator_uart_data ) ;
2005-04-17 02:20:36 +04:00
2012-06-11 02:14:15 +04:00
static AMBA_APB_DEVICE ( kmi0 , " kmi0 " , 0 , KMI0_BASE , KMI0_IRQ , NULL ) ;
static AMBA_APB_DEVICE ( kmi1 , " kmi1 " , 0 , KMI1_BASE , KMI1_IRQ , NULL ) ;
2005-04-17 02:20:36 +04:00
static struct amba_device * amba_devs [ ] __initdata = {
& rtc_device ,
& uart0_device ,
& uart1_device ,
& kmi0_device ,
& kmi1_device ,
} ;
2008-11-08 23:08:08 +03:00
/*
* These are fixed clocks .
*/
static struct clk clk24mhz = {
. rate = 24000000 ,
} ;
static struct clk uartclk = {
. rate = 14745600 ,
} ;
2010-07-15 14:01:17 +04:00
static struct clk dummy_apb_pclk ;
2009-05-18 20:26:08 +04:00
static struct clk_lookup lookups [ ] = {
2010-07-15 14:01:17 +04:00
{ /* Bus clock */
. con_id = " apb_pclk " ,
. clk = & dummy_apb_pclk ,
2011-09-09 00:23:15 +04:00
} , {
/* Integrator/AP timer frequency */
. dev_id = " ap_timer " ,
. clk = & clk24mhz ,
2010-07-15 14:01:17 +04:00
} , { /* UART0 */
2012-06-11 02:14:15 +04:00
. dev_id = " uart0 " ,
2008-11-08 23:08:08 +03:00
. clk = & uartclk ,
} , { /* UART1 */
2012-06-11 02:14:15 +04:00
. dev_id = " uart1 " ,
2008-11-08 23:08:08 +03:00
. clk = & uartclk ,
} , { /* KMI0 */
2012-06-11 02:14:15 +04:00
. dev_id = " kmi0 " ,
2008-11-08 23:08:08 +03:00
. clk = & clk24mhz ,
} , { /* KMI1 */
2012-06-11 02:14:15 +04:00
. dev_id = " kmi1 " ,
2008-11-08 23:08:08 +03:00
. clk = & clk24mhz ,
} , { /* MMCI - IntegratorCP */
2012-06-11 02:14:15 +04:00
. dev_id = " mmci " ,
2008-11-08 23:08:08 +03:00
. clk = & uartclk ,
}
} ;
2011-01-11 16:00:04 +03:00
void __init integrator_init_early ( void )
{
clkdev_add_table ( lookups , ARRAY_SIZE ( lookups ) ) ;
}
2005-04-17 02:20:36 +04:00
static int __init integrator_init ( void )
{
int i ;
2011-12-20 14:55:19 +04:00
/*
* The Integrator / AP lacks necessary AMBA PrimeCell IDs , so we need to
* hard - code them . The Integator / CP and forward have proper cell IDs .
* Else we leave them undefined to the bus driver can autoprobe them .
*/
if ( machine_is_integrator ( ) ) {
rtc_device . periphid = 0x00041030 ;
uart0_device . periphid = 0x00041010 ;
uart1_device . periphid = 0x00041010 ;
kmi0_device . periphid = 0x00041050 ;
kmi1_device . periphid = 0x00041050 ;
}
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( amba_devs ) ; i + + ) {
struct amba_device * d = amba_devs [ i ] ;
amba_device_register ( d , & iomem_resource ) ;
}
return 0 ;
}
arch_initcall ( integrator_init ) ;
2006-03-27 02:13:39 +04:00
/*
* On the Integrator platform , the port RTS and DTR are provided by
* bits in the following SC_CTRLS register bits :
* RTS DTR
* UART0 7 6
* UART1 5 4
*/
2010-01-17 23:45:12 +03:00
# define SC_CTRLC IO_ADDRESS(INTEGRATOR_SC_CTRLC)
# define SC_CTRLS IO_ADDRESS(INTEGRATOR_SC_CTRLS)
2006-03-27 02:13:39 +04:00
static void integrator_uart_set_mctrl ( struct amba_device * dev , void __iomem * base , unsigned int mctrl )
{
unsigned int ctrls = 0 , ctrlc = 0 , rts_mask , dtr_mask ;
if ( dev = = & uart0_device ) {
rts_mask = 1 < < 4 ;
dtr_mask = 1 < < 5 ;
} else {
rts_mask = 1 < < 6 ;
dtr_mask = 1 < < 7 ;
}
if ( mctrl & TIOCM_RTS )
ctrlc | = rts_mask ;
else
ctrls | = rts_mask ;
if ( mctrl & TIOCM_DTR )
ctrlc | = dtr_mask ;
else
ctrls | = dtr_mask ;
__raw_writel ( ctrls , SC_CTRLS ) ;
__raw_writel ( ctrlc , SC_CTRLC ) ;
}
static struct amba_pl010_data integrator_uart_data = {
. set_mctrl = integrator_uart_set_mctrl ,
} ;
2010-01-17 23:45:12 +03:00
# define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL)
2005-04-17 02:20:36 +04:00
2009-07-03 17:44:46 +04:00
static DEFINE_RAW_SPINLOCK ( cm_lock ) ;
2005-04-17 02:20:36 +04:00
/**
* cm_control - update the CM_CTRL register .
* @ mask : bits to change
* @ set : bits to set
*/
void cm_control ( u32 mask , u32 set )
{
unsigned long flags ;
u32 val ;
2009-07-03 17:44:46 +04:00
raw_spin_lock_irqsave ( & cm_lock , flags ) ;
2005-04-17 02:20:36 +04:00
val = readl ( CM_CTRL ) & ~ mask ;
writel ( val | set , CM_CTRL ) ;
2009-07-03 17:44:46 +04:00
raw_spin_unlock_irqrestore ( & cm_lock , flags ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( cm_control ) ;
2010-05-22 21:18:57 +04:00
/*
* We need to stop things allocating the low memory ; ideally we need a
* better implementation of GFP_DMA which does not assume that DMA - able
* memory starts at zero .
*/
void __init integrator_reserve ( void )
{
2010-05-22 22:47:18 +04:00
memblock_reserve ( PHYS_OFFSET , __pa ( swapper_pg_dir ) - PHYS_OFFSET ) ;
2010-05-22 21:18:57 +04:00
}
2011-11-03 23:54:37 +04:00
/*
* To reset , we hit the on - board reset register in the system FPGA
*/
void integrator_restart ( char mode , const char * cmd )
{
cm_control ( CM_CTRL_RESET , CM_CTRL_RESET ) ;
}