2009-03-27 14:25:49 +01:00
/*
2013-08-27 12:02:54 +02:00
* Copyright ( C ) 2007 - 2013 Michal Simek < monstr @ monstr . eu >
* Copyright ( C ) 2012 - 2013 Xilinx , Inc .
2009-03-27 14:25:49 +01: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>
2017-02-01 16:36:40 +01:00
# include <linux/sched/clock.h>
2013-12-20 10:16:40 +01:00
# include <linux/sched_clock.h>
2009-03-27 14:25:49 +01:00
# include <linux/clk.h>
# include <linux/clockchips.h>
2013-08-27 11:52:32 +02:00
# include <linux/of_address.h>
2013-09-07 14:05:10 -05:00
# include <linux/of_irq.h>
2015-01-02 20:22:09 +01:00
# include <linux/timecounter.h>
2009-03-27 14:25:49 +01:00
# include <asm/cpuinfo.h>
2013-08-27 11:52:32 +02:00
static void __iomem * timer_baseaddr ;
2009-03-27 14:25:49 +01:00
2011-02-07 11:33:47 +01:00
static unsigned int freq_div_hz ;
static unsigned int timer_clock_freq ;
2010-10-07 17:39:21 +10:00
2009-03-27 14:25:49 +01: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 15:04:03 +01: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 12:04:39 +02:00
static inline void xilinx_timer0_stop ( void )
2009-03-27 14:25:49 +01:00
{
2014-02-24 15:04:03 +01:00
write_fn ( read_fn ( timer_baseaddr + TCSR0 ) & ~ TCSR_ENT ,
timer_baseaddr + TCSR0 ) ;
2009-03-27 14:25:49 +01:00
}
2013-08-27 12:04:39 +02:00
static inline void xilinx_timer0_start_periodic ( unsigned long load_val )
2009-03-27 14:25:49 +01:00
{
if ( ! load_val )
load_val = 1 ;
2013-08-27 09:57:52 +02:00
/* loading value to timer reg */
2014-02-24 15:04:03 +01:00
write_fn ( load_val , timer_baseaddr + TLR0 ) ;
2009-03-27 14:25:49 +01:00
/* load the initial value */
2014-02-24 15:04:03 +01:00
write_fn ( TCSR_LOAD , timer_baseaddr + TCSR0 ) ;
2009-03-27 14:25:49 +01: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 15:49:22 +02:00
* ENIT - enable interrupt
2009-03-27 14:25:49 +01: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 15:04:03 +01:00
write_fn ( TCSR_TINT | TCSR_ENIT | TCSR_ENT | TCSR_ARHT | TCSR_UDT ,
timer_baseaddr + TCSR0 ) ;
2009-03-27 14:25:49 +01:00
}
2013-08-27 12:04:39 +02:00
static inline void xilinx_timer0_start_oneshot ( unsigned long load_val )
2009-03-27 14:25:49 +01:00
{
if ( ! load_val )
load_val = 1 ;
2013-08-27 09:57:52 +02:00
/* loading value to timer reg */
2014-02-24 15:04:03 +01:00
write_fn ( load_val , timer_baseaddr + TLR0 ) ;
2009-03-27 14:25:49 +01:00
/* load the initial value */
2014-02-24 15:04:03 +01:00
write_fn ( TCSR_LOAD , timer_baseaddr + TCSR0 ) ;
2009-03-27 14:25:49 +01:00
2014-02-24 15:04:03 +01:00
write_fn ( TCSR_TINT | TCSR_ENIT | TCSR_ENT | TCSR_ARHT | TCSR_UDT ,
timer_baseaddr + TCSR0 ) ;
2009-03-27 14:25:49 +01:00
}
2013-08-27 12:04:39 +02:00
static int xilinx_timer_set_next_event ( unsigned long delta ,
2009-03-27 14:25:49 +01:00
struct clock_event_device * dev )
{
pr_debug ( " %s: next event, delta %x \n " , __func__ , ( u32 ) delta ) ;
2013-08-27 12:04:39 +02:00
xilinx_timer0_start_oneshot ( delta ) ;
2009-03-27 14:25:49 +01:00
return 0 ;
}
2015-07-16 16:56:21 +05:30
static int xilinx_timer_shutdown ( struct clock_event_device * evt )
2009-03-27 14:25:49 +01:00
{
2015-07-16 16:56:21 +05:30
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 14:25:49 +01:00
}
2013-08-27 12:04:39 +02:00
static struct clock_event_device clockevent_xilinx_timer = {
2015-07-16 16:56:21 +05:30
. 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 14:25:49 +01:00
} ;
static inline void timer_ack ( void )
{
2014-02-24 15:04:03 +01:00
write_fn ( read_fn ( timer_baseaddr + TCSR0 ) , timer_baseaddr + TCSR0 ) ;
2009-03-27 14:25:49 +01:00
}
static irqreturn_t timer_interrupt ( int irq , void * dev_id )
{
2013-08-27 12:04:39 +02:00
struct clock_event_device * evt = & clockevent_xilinx_timer ;
2009-03-27 14:25:49 +01:00
timer_ack ( ) ;
evt - > event_handler ( evt ) ;
return IRQ_HANDLED ;
}
2016-06-07 00:03:34 +02:00
static __init int xilinx_clockevent_init ( void )
2009-03-27 14:25:49 +01:00
{
2013-08-27 12:04:39 +02:00
clockevent_xilinx_timer . mult =
2010-10-07 17:39:21 +10:00
div_sc ( timer_clock_freq , NSEC_PER_SEC ,
2013-08-27 12:04:39 +02:00
clockevent_xilinx_timer . shift ) ;
clockevent_xilinx_timer . max_delta_ns =
clockevent_delta2ns ( ( u32 ) ~ 0 , & clockevent_xilinx_timer ) ;
2017-03-30 21:45:28 +02:00
clockevent_xilinx_timer . max_delta_ticks = ( u32 ) ~ 0 ;
2013-08-27 12:04:39 +02:00
clockevent_xilinx_timer . min_delta_ns =
clockevent_delta2ns ( 1 , & clockevent_xilinx_timer ) ;
2017-03-30 21:45:28 +02:00
clockevent_xilinx_timer . min_delta_ticks = 1 ;
2013-08-27 12:04:39 +02:00
clockevent_xilinx_timer . cpumask = cpumask_of ( 0 ) ;
clockevents_register_device ( & clockevent_xilinx_timer ) ;
2016-06-07 00:03:34 +02:00
return 0 ;
2009-03-27 14:25:49 +01:00
}
2013-12-20 10:16:40 +01:00
static u64 xilinx_clock_read ( void )
{
2014-02-24 15:04:03 +01:00
return read_fn ( timer_baseaddr + TCR1 ) ;
2013-12-20 10:16:40 +01:00
}
2016-12-21 20:32:01 +01:00
static u64 xilinx_read ( struct clocksource * cs )
2009-03-27 14:25:49 +01:00
{
/* reading actual value of timer 1 */
2016-12-21 20:32:01 +01:00
return ( u64 ) xilinx_clock_read ( ) ;
2009-03-27 14:25:49 +01:00
}
2013-08-27 12:04:39 +02:00
static struct timecounter xilinx_tc = {
2009-11-06 12:31:00 +01:00
. cc = NULL ,
} ;
2016-12-21 20:32:01 +01:00
static u64 xilinx_cc_read ( const struct cyclecounter * cc )
2009-11-06 12:31:00 +01:00
{
2013-08-27 12:04:39 +02:00
return xilinx_read ( NULL ) ;
2009-11-06 12:31:00 +01:00
}
2013-08-27 12:04:39 +02:00
static struct cyclecounter xilinx_cc = {
. read = xilinx_cc_read ,
2009-11-06 12:31:00 +01:00
. mask = CLOCKSOURCE_MASK ( 32 ) ,
2010-06-10 16:04:05 +02:00
. shift = 8 ,
2009-11-06 12:31:00 +01:00
} ;
2013-08-27 12:04:39 +02:00
static int __init init_xilinx_timecounter ( void )
2009-11-06 12:31:00 +01:00
{
2013-08-27 12:04:39 +02:00
xilinx_cc . mult = div_sc ( timer_clock_freq , NSEC_PER_SEC ,
xilinx_cc . shift ) ;
2009-11-06 12:31:00 +01:00
2013-08-27 12:04:39 +02:00
timecounter_init ( & xilinx_tc , & xilinx_cc , sched_clock ( ) ) ;
2009-11-06 12:31:00 +01:00
return 0 ;
}
2009-03-27 14:25:49 +01:00
static struct clocksource clocksource_microblaze = {
2013-08-27 12:04:39 +02:00
. name = " xilinx_clocksource " ,
2009-03-27 14:25:49 +01:00
. rating = 300 ,
2013-08-27 12:04:39 +02:00
. read = xilinx_read ,
2009-03-27 14:25:49 +01:00
. mask = CLOCKSOURCE_MASK ( 32 ) ,
. flags = CLOCK_SOURCE_IS_CONTINUOUS ,
} ;
2013-08-27 12:04:39 +02:00
static int __init xilinx_clocksource_init ( void )
2009-03-27 14:25:49 +01:00
{
2016-06-07 00:03:34 +02: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 14:25:49 +01:00
/* stop timer1 */
2014-02-24 15:04:03 +01:00
write_fn ( read_fn ( timer_baseaddr + TCSR1 ) & ~ TCSR_ENT ,
timer_baseaddr + TCSR1 ) ;
2009-03-27 14:25:49 +01:00
/* start timer1 - up counting without interrupt */
2014-02-24 15:04:03 +01:00
write_fn ( TCSR_TINT | TCSR_ENT | TCSR_ARHT , timer_baseaddr + TCSR1 ) ;
2009-11-06 12:31:00 +01:00
/* register timecounter - for ftrace support */
2016-06-07 00:03:34 +02:00
return init_xilinx_timecounter ( ) ;
2009-03-27 14:25:49 +01:00
}
2016-06-07 00:03:34 +02:00
static int __init xilinx_timer_init ( struct device_node * timer )
2009-03-27 14:25:49 +01:00
{
2013-12-18 17:18:48 +01:00
struct clk * clk ;
2014-01-27 10:41:59 +01:00
static int initialized ;
2011-12-09 12:26:16 +01:00
u32 irq ;
2009-03-27 14:25:49 +01:00
u32 timer_num = 1 ;
2016-06-07 00:03:34 +02:00
int ret ;
2013-08-27 11:52:32 +02:00
2014-01-27 10:41:59 +01:00
if ( initialized )
2016-11-15 11:53:54 +01:00
return - EINVAL ;
2014-01-27 10:41:59 +01:00
initialized = 1 ;
2013-08-27 11:52:32 +02:00
timer_baseaddr = of_iomap ( timer , 0 ) ;
if ( ! timer_baseaddr ) {
pr_err ( " ERROR: invalid timer base address \n " ) ;
2016-06-07 00:03:34 +02:00
return - ENXIO ;
2013-08-27 11:52:32 +02:00
}
2013-08-27 09:57:52 +02:00
2014-02-24 15:04:03 +01: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 10:46:52 +01:00
irq = irq_of_parse_and_map ( timer , 0 ) ;
2016-06-07 00:03:34 +02:00
if ( irq < = 0 ) {
pr_err ( " Failed to parse and map irq " ) ;
return - EINVAL ;
}
2013-08-27 11:52:32 +02:00
of_property_read_u32 ( timer , " xlnx,one-timer-only " , & timer_num ) ;
2009-03-27 14:25:49 +01:00
if ( timer_num ) {
2016-06-07 00:03:34 +02:00
pr_err ( " Please enable two timers in HW \n " ) ;
return - EINVAL ;
2009-03-27 14:25:49 +01:00
}
2017-06-06 15:57:36 -05:00
pr_info ( " %pOF: irq=%d \n " , timer , irq ) ;
2009-03-27 14:25:49 +01:00
2013-12-18 17:18:48 +01: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 17:39:21 +10:00
timer_clock_freq = cpuinfo . cpu_clock_freq ;
2013-12-18 17:18:48 +01:00
}
2010-10-07 17:39:21 +10:00
freq_div_hz = timer_clock_freq / HZ ;
2009-03-27 14:25:49 +01:00
2020-03-04 06:19:59 +05:30
ret = request_irq ( irq , timer_interrupt , IRQF_TIMER , " timer " ,
& clockevent_xilinx_timer ) ;
2016-06-07 00:03:34 +02:00
if ( ret ) {
pr_err ( " Failed to setup IRQ " ) ;
return ret ;
}
ret = xilinx_clocksource_init ( ) ;
if ( ret )
return ret ;
ret = xilinx_clockevent_init ( ) ;
if ( ret )
return ret ;
2011-09-23 09:52:24 +02:00
2013-12-20 10:16:40 +01:00
sched_clock_register ( xilinx_clock_read , 32 , timer_clock_freq ) ;
2016-06-07 00:03:34 +02:00
return 0 ;
2009-03-27 14:25:49 +01:00
}
2013-08-27 11:13:29 +02:00
2017-05-26 16:56:11 +02:00
TIMER_OF_DECLARE ( xilinx_timer , " xlnx,xps-timer-1.00.a " ,
2013-08-27 11:13:29 +02:00
xilinx_timer_init ) ;