2009-03-27 16:25:49 +03:00
/*
2013-08-27 14:02:54 +04:00
* Copyright ( C ) 2007 - 2013 Michal Simek < monstr @ monstr . eu >
* Copyright ( C ) 2012 - 2013 Xilinx , Inc .
2009-03-27 16:25:49 +03:00
* Copyright ( C ) 2007 - 2009 PetaLogix
* Copyright ( C ) 2006 Atmark Techno , Inc .
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/sched.h>
2013-12-20 13:16:40 +04:00
# include <linux/sched_clock.h>
2009-03-27 16:25:49 +03:00
# include <linux/clk.h>
# include <linux/clockchips.h>
2013-08-27 13:52:32 +04:00
# include <linux/of_address.h>
2013-09-07 23:05:10 +04:00
# include <linux/of_irq.h>
2015-01-02 22:22:09 +03:00
# include <linux/timecounter.h>
2009-03-27 16:25:49 +03:00
# include <asm/cpuinfo.h>
2013-08-27 13:52:32 +04:00
static void __iomem * timer_baseaddr ;
2009-03-27 16:25:49 +03:00
2011-02-07 13:33:47 +03:00
static unsigned int freq_div_hz ;
static unsigned int timer_clock_freq ;
2010-10-07 11:39:21 +04:00
2009-03-27 16:25:49 +03:00
# define TCSR0 (0x00)
# define TLR0 (0x04)
# define TCR0 (0x08)
# define TCSR1 (0x10)
# define TLR1 (0x14)
# define TCR1 (0x18)
# define TCSR_MDT (1<<0)
# define TCSR_UDT (1<<1)
# define TCSR_GENT (1<<2)
# define TCSR_CAPT (1<<3)
# define TCSR_ARHT (1<<4)
# define TCSR_LOAD (1<<5)
# define TCSR_ENIT (1<<6)
# define TCSR_ENT (1<<7)
# define TCSR_TINT (1<<8)
# define TCSR_PWMA (1<<9)
# define TCSR_ENALL (1<<10)
2014-02-24 18:04:03 +04:00
static unsigned int ( * read_fn ) ( void __iomem * ) ;
static void ( * write_fn ) ( u32 , void __iomem * ) ;
static void timer_write32 ( u32 val , void __iomem * addr )
{
iowrite32 ( val , addr ) ;
}
static unsigned int timer_read32 ( void __iomem * addr )
{
return ioread32 ( addr ) ;
}
static void timer_write32_be ( u32 val , void __iomem * addr )
{
iowrite32be ( val , addr ) ;
}
static unsigned int timer_read32_be ( void __iomem * addr )
{
return ioread32be ( addr ) ;
}
2013-08-27 14:04:39 +04:00
static inline void xilinx_timer0_stop ( void )
2009-03-27 16:25:49 +03:00
{
2014-02-24 18:04:03 +04:00
write_fn ( read_fn ( timer_baseaddr + TCSR0 ) & ~ TCSR_ENT ,
timer_baseaddr + TCSR0 ) ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 14:04:39 +04:00
static inline void xilinx_timer0_start_periodic ( unsigned long load_val )
2009-03-27 16:25:49 +03:00
{
if ( ! load_val )
load_val = 1 ;
2013-08-27 11:57:52 +04:00
/* loading value to timer reg */
2014-02-24 18:04:03 +04:00
write_fn ( load_val , timer_baseaddr + TLR0 ) ;
2009-03-27 16:25:49 +03:00
/* load the initial value */
2014-02-24 18:04:03 +04:00
write_fn ( TCSR_LOAD , timer_baseaddr + TCSR0 ) ;
2009-03-27 16:25:49 +03:00
/* see timer data sheet for detail
* ! ENALL - don ' t enable ' em all
* ! PWMA - disable pwm
* TINT - clear interrupt status
* ENT - enable timer itself
2011-04-05 17:49:22 +04:00
* ENIT - enable interrupt
2009-03-27 16:25:49 +03:00
* ! LOAD - clear the bit to let go
* ARHT - auto reload
* ! CAPT - no external trigger
* ! GENT - no external signal
* UDT - set the timer as down counter
* ! MDT0 - generate mode
*/
2014-02-24 18:04:03 +04:00
write_fn ( TCSR_TINT | TCSR_ENIT | TCSR_ENT | TCSR_ARHT | TCSR_UDT ,
timer_baseaddr + TCSR0 ) ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 14:04:39 +04:00
static inline void xilinx_timer0_start_oneshot ( unsigned long load_val )
2009-03-27 16:25:49 +03:00
{
if ( ! load_val )
load_val = 1 ;
2013-08-27 11:57:52 +04:00
/* loading value to timer reg */
2014-02-24 18:04:03 +04:00
write_fn ( load_val , timer_baseaddr + TLR0 ) ;
2009-03-27 16:25:49 +03:00
/* load the initial value */
2014-02-24 18:04:03 +04:00
write_fn ( TCSR_LOAD , timer_baseaddr + TCSR0 ) ;
2009-03-27 16:25:49 +03:00
2014-02-24 18:04:03 +04:00
write_fn ( TCSR_TINT | TCSR_ENIT | TCSR_ENT | TCSR_ARHT | TCSR_UDT ,
timer_baseaddr + TCSR0 ) ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 14:04:39 +04:00
static int xilinx_timer_set_next_event ( unsigned long delta ,
2009-03-27 16:25:49 +03:00
struct clock_event_device * dev )
{
pr_debug ( " %s: next event, delta %x \n " , __func__ , ( u32 ) delta ) ;
2013-08-27 14:04:39 +04:00
xilinx_timer0_start_oneshot ( delta ) ;
2009-03-27 16:25:49 +03:00
return 0 ;
}
2015-07-16 14:26:21 +03:00
static int xilinx_timer_shutdown ( struct clock_event_device * evt )
2009-03-27 16:25:49 +03:00
{
2015-07-16 14:26:21 +03:00
pr_info ( " %s \n " , __func__ ) ;
xilinx_timer0_stop ( ) ;
return 0 ;
}
static int xilinx_timer_set_periodic ( struct clock_event_device * evt )
{
pr_info ( " %s \n " , __func__ ) ;
xilinx_timer0_start_periodic ( freq_div_hz ) ;
return 0 ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 14:04:39 +04:00
static struct clock_event_device clockevent_xilinx_timer = {
2015-07-16 14:26:21 +03:00
. name = " xilinx_clockevent " ,
. features = CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_PERIODIC ,
. shift = 8 ,
. rating = 300 ,
. set_next_event = xilinx_timer_set_next_event ,
. set_state_shutdown = xilinx_timer_shutdown ,
. set_state_periodic = xilinx_timer_set_periodic ,
2009-03-27 16:25:49 +03:00
} ;
static inline void timer_ack ( void )
{
2014-02-24 18:04:03 +04:00
write_fn ( read_fn ( timer_baseaddr + TCSR0 ) , timer_baseaddr + TCSR0 ) ;
2009-03-27 16:25:49 +03:00
}
static irqreturn_t timer_interrupt ( int irq , void * dev_id )
{
2013-08-27 14:04:39 +04:00
struct clock_event_device * evt = & clockevent_xilinx_timer ;
2009-03-27 16:25:49 +03:00
# ifdef CONFIG_HEART_BEAT
2014-02-18 10:46:54 +04:00
microblaze_heartbeat ( ) ;
2009-03-27 16:25:49 +03:00
# endif
timer_ack ( ) ;
evt - > event_handler ( evt ) ;
return IRQ_HANDLED ;
}
static struct irqaction timer_irqaction = {
. handler = timer_interrupt ,
2013-08-20 18:45:36 +04:00
. flags = IRQF_TIMER ,
2009-03-27 16:25:49 +03:00
. name = " timer " ,
2013-08-27 14:04:39 +04:00
. dev_id = & clockevent_xilinx_timer ,
2009-03-27 16:25:49 +03:00
} ;
2016-06-07 01:03:34 +03:00
static __init int xilinx_clockevent_init ( void )
2009-03-27 16:25:49 +03:00
{
2013-08-27 14:04:39 +04:00
clockevent_xilinx_timer . mult =
2010-10-07 11:39:21 +04:00
div_sc ( timer_clock_freq , NSEC_PER_SEC ,
2013-08-27 14:04:39 +04:00
clockevent_xilinx_timer . shift ) ;
clockevent_xilinx_timer . max_delta_ns =
clockevent_delta2ns ( ( u32 ) ~ 0 , & clockevent_xilinx_timer ) ;
clockevent_xilinx_timer . min_delta_ns =
clockevent_delta2ns ( 1 , & clockevent_xilinx_timer ) ;
clockevent_xilinx_timer . cpumask = cpumask_of ( 0 ) ;
clockevents_register_device ( & clockevent_xilinx_timer ) ;
2016-06-07 01:03:34 +03:00
return 0 ;
2009-03-27 16:25:49 +03:00
}
2013-12-20 13:16:40 +04:00
static u64 xilinx_clock_read ( void )
{
2014-02-24 18:04:03 +04:00
return read_fn ( timer_baseaddr + TCR1 ) ;
2013-12-20 13:16:40 +04:00
}
2013-08-27 14:04:39 +04:00
static cycle_t xilinx_read ( struct clocksource * cs )
2009-03-27 16:25:49 +03:00
{
/* reading actual value of timer 1 */
2013-12-20 13:16:40 +04:00
return ( cycle_t ) xilinx_clock_read ( ) ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 14:04:39 +04:00
static struct timecounter xilinx_tc = {
2009-11-06 14:31:00 +03:00
. cc = NULL ,
} ;
2013-08-27 14:04:39 +04:00
static cycle_t xilinx_cc_read ( const struct cyclecounter * cc )
2009-11-06 14:31:00 +03:00
{
2013-08-27 14:04:39 +04:00
return xilinx_read ( NULL ) ;
2009-11-06 14:31:00 +03:00
}
2013-08-27 14:04:39 +04:00
static struct cyclecounter xilinx_cc = {
. read = xilinx_cc_read ,
2009-11-06 14:31:00 +03:00
. mask = CLOCKSOURCE_MASK ( 32 ) ,
2010-06-10 18:04:05 +04:00
. shift = 8 ,
2009-11-06 14:31:00 +03:00
} ;
2013-08-27 14:04:39 +04:00
static int __init init_xilinx_timecounter ( void )
2009-11-06 14:31:00 +03:00
{
2013-08-27 14:04:39 +04:00
xilinx_cc . mult = div_sc ( timer_clock_freq , NSEC_PER_SEC ,
xilinx_cc . shift ) ;
2009-11-06 14:31:00 +03:00
2013-08-27 14:04:39 +04:00
timecounter_init ( & xilinx_tc , & xilinx_cc , sched_clock ( ) ) ;
2009-11-06 14:31:00 +03:00
return 0 ;
}
2009-03-27 16:25:49 +03:00
static struct clocksource clocksource_microblaze = {
2013-08-27 14:04:39 +04:00
. name = " xilinx_clocksource " ,
2009-03-27 16:25:49 +03:00
. rating = 300 ,
2013-08-27 14:04:39 +04:00
. read = xilinx_read ,
2009-03-27 16:25:49 +03:00
. mask = CLOCKSOURCE_MASK ( 32 ) ,
. flags = CLOCK_SOURCE_IS_CONTINUOUS ,
} ;
2013-08-27 14:04:39 +04:00
static int __init xilinx_clocksource_init ( void )
2009-03-27 16:25:49 +03:00
{
2016-06-07 01:03:34 +03:00
int ret ;
ret = clocksource_register_hz ( & clocksource_microblaze ,
timer_clock_freq ) ;
if ( ret ) {
pr_err ( " failed to register clocksource " ) ;
return ret ;
}
2009-03-27 16:25:49 +03:00
/* stop timer1 */
2014-02-24 18:04:03 +04:00
write_fn ( read_fn ( timer_baseaddr + TCSR1 ) & ~ TCSR_ENT ,
timer_baseaddr + TCSR1 ) ;
2009-03-27 16:25:49 +03:00
/* start timer1 - up counting without interrupt */
2014-02-24 18:04:03 +04:00
write_fn ( TCSR_TINT | TCSR_ENT | TCSR_ARHT , timer_baseaddr + TCSR1 ) ;
2009-11-06 14:31:00 +03:00
/* register timecounter - for ftrace support */
2016-06-07 01:03:34 +03:00
return init_xilinx_timecounter ( ) ;
2009-03-27 16:25:49 +03:00
}
2016-06-07 01:03:34 +03:00
static int __init xilinx_timer_init ( struct device_node * timer )
2009-03-27 16:25:49 +03:00
{
2013-12-18 20:18:48 +04:00
struct clk * clk ;
2014-01-27 13:41:59 +04:00
static int initialized ;
2011-12-09 15:26:16 +04:00
u32 irq ;
2009-03-27 16:25:49 +03:00
u32 timer_num = 1 ;
2016-06-07 01:03:34 +03:00
int ret ;
2013-08-27 13:52:32 +04:00
2014-01-27 13:41:59 +04:00
if ( initialized )
return ;
initialized = 1 ;
2013-08-27 13:52:32 +04:00
timer_baseaddr = of_iomap ( timer , 0 ) ;
if ( ! timer_baseaddr ) {
pr_err ( " ERROR: invalid timer base address \n " ) ;
2016-06-07 01:03:34 +03:00
return - ENXIO ;
2013-08-27 13:52:32 +04:00
}
2013-08-27 11:57:52 +04:00
2014-02-24 18:04:03 +04:00
write_fn = timer_write32 ;
read_fn = timer_read32 ;
write_fn ( TCSR_MDT , timer_baseaddr + TCSR0 ) ;
if ( ! ( read_fn ( timer_baseaddr + TCSR0 ) & TCSR_MDT ) ) {
write_fn = timer_write32_be ;
read_fn = timer_read32_be ;
}
2011-12-09 13:46:52 +04:00
irq = irq_of_parse_and_map ( timer , 0 ) ;
2016-06-07 01:03:34 +03:00
if ( irq < = 0 ) {
pr_err ( " Failed to parse and map irq " ) ;
return - EINVAL ;
}
2013-08-27 13:52:32 +04:00
of_property_read_u32 ( timer , " xlnx,one-timer-only " , & timer_num ) ;
2009-03-27 16:25:49 +03:00
if ( timer_num ) {
2016-06-07 01:03:34 +03:00
pr_err ( " Please enable two timers in HW \n " ) ;
return - EINVAL ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 13:52:32 +04:00
pr_info ( " %s: irq=%d \n " , timer - > full_name , irq ) ;
2009-03-27 16:25:49 +03:00
2013-12-18 20:18:48 +04:00
clk = of_clk_get ( timer , 0 ) ;
if ( IS_ERR ( clk ) ) {
pr_err ( " ERROR: timer CCF input clock not found \n " ) ;
/* If there is clock-frequency property than use it */
of_property_read_u32 ( timer , " clock-frequency " ,
& timer_clock_freq ) ;
} else {
timer_clock_freq = clk_get_rate ( clk ) ;
}
if ( ! timer_clock_freq ) {
pr_err ( " ERROR: Using CPU clock frequency \n " ) ;
2010-10-07 11:39:21 +04:00
timer_clock_freq = cpuinfo . cpu_clock_freq ;
2013-12-18 20:18:48 +04:00
}
2010-10-07 11:39:21 +04:00
freq_div_hz = timer_clock_freq / HZ ;
2009-03-27 16:25:49 +03:00
2016-06-07 01:03:34 +03:00
ret = setup_irq ( irq , & timer_irqaction ) ;
if ( ret ) {
pr_err ( " Failed to setup IRQ " ) ;
return ret ;
}
2009-03-27 16:25:49 +03:00
# ifdef CONFIG_HEART_BEAT
2014-02-18 10:46:54 +04:00
microblaze_setup_heartbeat ( ) ;
2009-03-27 16:25:49 +03:00
# endif
2016-06-07 01:03:34 +03:00
ret = xilinx_clocksource_init ( ) ;
if ( ret )
return ret ;
ret = xilinx_clockevent_init ( ) ;
if ( ret )
return ret ;
2011-09-23 11:52:24 +04:00
2013-12-20 13:16:40 +04:00
sched_clock_register ( xilinx_clock_read , 32 , timer_clock_freq ) ;
2016-06-07 01:03:34 +03:00
return 0 ;
2009-03-27 16:25:49 +03:00
}
2013-08-27 13:13:29 +04:00
2016-06-07 01:27:44 +03:00
CLOCKSOURCE_OF_DECLARE ( xilinx_timer , " xlnx,xps-timer-1.00.a " ,
2013-08-27 13:13:29 +04:00
xilinx_timer_init ) ;