2018-11-10 18:28:39 +03:00
// SPDX-License-Identifier: GPL-2.0+
2012-09-11 08:38:35 +04:00
/*
* Copyright 2012 Simon Arlott
*/
# include <linux/bitops.h>
# include <linux/clockchips.h>
# include <linux/clocksource.h>
# include <linux/interrupt.h>
# include <linux/irqreturn.h>
# include <linux/kernel.h>
# include <linux/module.h>
2023-07-14 20:44:09 +03:00
# include <linux/of.h>
2012-09-11 08:38:35 +04:00
# include <linux/of_address.h>
# include <linux/of_irq.h>
# include <linux/slab.h>
# include <linux/string.h>
2013-06-02 10:39:40 +04:00
# include <linux/sched_clock.h>
2012-09-11 08:38:35 +04:00
# include <asm/irq.h>
# define REG_CONTROL 0x00
# define REG_COUNTER_LO 0x04
# define REG_COUNTER_HI 0x08
# define REG_COMPARE(n) (0x0c + (n) * 4)
# define MAX_TIMER 3
# define DEFAULT_TIMER 3
struct bcm2835_timer {
void __iomem * control ;
void __iomem * compare ;
int match_mask ;
struct clock_event_device evt ;
} ;
static void __iomem * system_clock __read_mostly ;
2013-07-19 03:21:20 +04:00
static u64 notrace bcm2835_sched_read ( void )
2012-09-11 08:38:35 +04:00
{
return readl_relaxed ( system_clock ) ;
}
static int bcm2835_time_set_next_event ( unsigned long event ,
struct clock_event_device * evt_dev )
{
struct bcm2835_timer * timer = container_of ( evt_dev ,
struct bcm2835_timer , evt ) ;
writel_relaxed ( readl_relaxed ( system_clock ) + event ,
timer - > compare ) ;
return 0 ;
}
static irqreturn_t bcm2835_time_interrupt ( int irq , void * dev_id )
{
struct bcm2835_timer * timer = dev_id ;
void ( * event_handler ) ( struct clock_event_device * ) ;
if ( readl_relaxed ( timer - > control ) & timer - > match_mask ) {
writel_relaxed ( timer - > match_mask , timer - > control ) ;
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
event_handler = READ_ONCE ( timer - > evt . event_handler ) ;
2012-09-11 08:38:35 +04:00
if ( event_handler )
event_handler ( & timer - > evt ) ;
return IRQ_HANDLED ;
} else {
return IRQ_NONE ;
}
}
2016-06-02 19:46:11 +03:00
static int __init bcm2835_timer_init ( struct device_node * node )
2012-09-11 08:38:35 +04:00
{
void __iomem * base ;
u32 freq ;
2016-06-02 19:46:11 +03:00
int irq , ret ;
2012-09-11 08:38:35 +04:00
struct bcm2835_timer * timer ;
base = of_iomap ( node , 0 ) ;
2016-06-02 19:46:11 +03:00
if ( ! base ) {
2017-03-09 12:47:10 +03:00
pr_err ( " Can't remap registers \n " ) ;
2016-06-02 19:46:11 +03:00
return - ENXIO ;
}
2012-09-11 08:38:35 +04:00
2016-06-02 19:46:11 +03:00
ret = of_property_read_u32 ( node , " clock-frequency " , & freq ) ;
if ( ret ) {
2017-03-09 12:47:10 +03:00
pr_err ( " Can't read clock-frequency \n " ) ;
2016-09-21 20:33:57 +03:00
goto err_iounmap ;
2016-06-02 19:46:11 +03:00
}
2012-09-11 08:38:35 +04:00
system_clock = base + REG_COUNTER_LO ;
2013-07-19 03:21:20 +04:00
sched_clock_register ( bcm2835_sched_read , 32 , freq ) ;
2012-09-11 08:38:35 +04:00
clocksource_mmio_init ( base + REG_COUNTER_LO , node - > name ,
freq , 300 , 32 , clocksource_mmio_readl_up ) ;
irq = irq_of_parse_and_map ( node , DEFAULT_TIMER ) ;
2016-06-02 19:46:11 +03:00
if ( irq < = 0 ) {
2017-03-09 12:47:10 +03:00
pr_err ( " Can't parse IRQ \n " ) ;
2016-09-21 20:33:57 +03:00
ret = - EINVAL ;
goto err_iounmap ;
2016-06-02 19:46:11 +03:00
}
2012-09-11 08:38:35 +04:00
timer = kzalloc ( sizeof ( * timer ) , GFP_KERNEL ) ;
2016-06-02 19:46:11 +03:00
if ( ! timer ) {
2016-09-21 20:33:57 +03:00
ret = - ENOMEM ;
goto err_iounmap ;
2016-06-02 19:46:11 +03:00
}
2012-09-11 08:38:35 +04:00
timer - > control = base + REG_CONTROL ;
timer - > compare = base + REG_COMPARE ( DEFAULT_TIMER ) ;
timer - > match_mask = BIT ( DEFAULT_TIMER ) ;
timer - > evt . name = node - > name ;
timer - > evt . rating = 300 ;
timer - > evt . features = CLOCK_EVT_FEAT_ONESHOT ;
timer - > evt . set_next_event = bcm2835_time_set_next_event ;
timer - > evt . cpumask = cpumask_of ( 0 ) ;
2020-02-27 13:59:02 +03:00
ret = request_irq ( irq , bcm2835_time_interrupt , IRQF_TIMER | IRQF_SHARED ,
node - > name , timer ) ;
2016-06-02 19:46:11 +03:00
if ( ret ) {
pr_err ( " Can't set up timer IRQ \n " ) ;
2019-12-20 00:32:46 +03:00
goto err_timer_free ;
2016-06-02 19:46:11 +03:00
}
2012-09-11 08:38:35 +04:00
clockevents_config_and_register ( & timer - > evt , freq , 0xf , 0xffffffff ) ;
pr_info ( " bcm2835: system timer (irq = %d) \n " , irq ) ;
2016-06-02 19:46:11 +03:00
return 0 ;
2016-09-21 20:33:57 +03:00
2019-12-20 00:32:46 +03:00
err_timer_free :
kfree ( timer ) ;
2016-09-21 20:33:57 +03:00
err_iounmap :
iounmap ( base ) ;
return ret ;
2012-09-11 08:38:35 +04:00
}
2017-05-26 17:56:11 +03:00
TIMER_OF_DECLARE ( bcm2835 , " brcm,bcm2835-system-timer " ,
2013-01-04 07:23:13 +04:00
bcm2835_timer_init ) ;