1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017 Spreadtrum Communications Inc.
6 #include <linux/init.h>
7 #include <linux/interrupt.h>
11 #define TIMER_NAME "sprd_timer"
13 #define TIMER_LOAD_LO 0x0
14 #define TIMER_LOAD_HI 0x4
15 #define TIMER_VALUE_LO 0x8
16 #define TIMER_VALUE_HI 0xc
18 #define TIMER_CTL 0x10
19 #define TIMER_CTL_PERIOD_MODE BIT(0)
20 #define TIMER_CTL_ENABLE BIT(1)
21 #define TIMER_CTL_64BIT_WIDTH BIT(16)
23 #define TIMER_INT 0x14
24 #define TIMER_INT_EN BIT(0)
25 #define TIMER_INT_RAW_STS BIT(1)
26 #define TIMER_INT_MASK_STS BIT(2)
27 #define TIMER_INT_CLR BIT(3)
29 #define TIMER_VALUE_SHDW_LO 0x18
30 #define TIMER_VALUE_SHDW_HI 0x1c
32 #define TIMER_VALUE_LO_MASK GENMASK(31, 0)
34 static void sprd_timer_enable(void __iomem
*base
, u32 flag
)
36 u32 val
= readl_relaxed(base
+ TIMER_CTL
);
38 val
|= TIMER_CTL_ENABLE
;
39 if (flag
& TIMER_CTL_64BIT_WIDTH
)
40 val
|= TIMER_CTL_64BIT_WIDTH
;
42 val
&= ~TIMER_CTL_64BIT_WIDTH
;
44 if (flag
& TIMER_CTL_PERIOD_MODE
)
45 val
|= TIMER_CTL_PERIOD_MODE
;
47 val
&= ~TIMER_CTL_PERIOD_MODE
;
49 writel_relaxed(val
, base
+ TIMER_CTL
);
52 static void sprd_timer_disable(void __iomem
*base
)
54 u32 val
= readl_relaxed(base
+ TIMER_CTL
);
56 val
&= ~TIMER_CTL_ENABLE
;
57 writel_relaxed(val
, base
+ TIMER_CTL
);
60 static void sprd_timer_update_counter(void __iomem
*base
, unsigned long cycles
)
62 writel_relaxed(cycles
& TIMER_VALUE_LO_MASK
, base
+ TIMER_LOAD_LO
);
63 writel_relaxed(0, base
+ TIMER_LOAD_HI
);
66 static void sprd_timer_enable_interrupt(void __iomem
*base
)
68 writel_relaxed(TIMER_INT_EN
, base
+ TIMER_INT
);
71 static void sprd_timer_clear_interrupt(void __iomem
*base
)
73 u32 val
= readl_relaxed(base
+ TIMER_INT
);
76 writel_relaxed(val
, base
+ TIMER_INT
);
79 static int sprd_timer_set_next_event(unsigned long cycles
,
80 struct clock_event_device
*ce
)
82 struct timer_of
*to
= to_timer_of(ce
);
84 sprd_timer_disable(timer_of_base(to
));
85 sprd_timer_update_counter(timer_of_base(to
), cycles
);
86 sprd_timer_enable(timer_of_base(to
), 0);
91 static int sprd_timer_set_periodic(struct clock_event_device
*ce
)
93 struct timer_of
*to
= to_timer_of(ce
);
95 sprd_timer_disable(timer_of_base(to
));
96 sprd_timer_update_counter(timer_of_base(to
), timer_of_period(to
));
97 sprd_timer_enable(timer_of_base(to
), TIMER_CTL_PERIOD_MODE
);
102 static int sprd_timer_shutdown(struct clock_event_device
*ce
)
104 struct timer_of
*to
= to_timer_of(ce
);
106 sprd_timer_disable(timer_of_base(to
));
110 static irqreturn_t
sprd_timer_interrupt(int irq
, void *dev_id
)
112 struct clock_event_device
*ce
= (struct clock_event_device
*)dev_id
;
113 struct timer_of
*to
= to_timer_of(ce
);
115 sprd_timer_clear_interrupt(timer_of_base(to
));
117 if (clockevent_state_oneshot(ce
))
118 sprd_timer_disable(timer_of_base(to
));
120 ce
->event_handler(ce
);
124 static struct timer_of to
= {
125 .flags
= TIMER_OF_IRQ
| TIMER_OF_BASE
| TIMER_OF_CLOCK
,
130 .features
= CLOCK_EVT_FEAT_DYNIRQ
| CLOCK_EVT_FEAT_PERIODIC
|
131 CLOCK_EVT_FEAT_ONESHOT
,
132 .set_state_shutdown
= sprd_timer_shutdown
,
133 .set_state_periodic
= sprd_timer_set_periodic
,
134 .set_next_event
= sprd_timer_set_next_event
,
135 .cpumask
= cpu_possible_mask
,
139 .handler
= sprd_timer_interrupt
,
140 .flags
= IRQF_TIMER
| IRQF_IRQPOLL
,
144 static int __init
sprd_timer_init(struct device_node
*np
)
148 ret
= timer_of_init(np
, &to
);
152 sprd_timer_enable_interrupt(timer_of_base(&to
));
153 clockevents_config_and_register(&to
.clkevt
, timer_of_rate(&to
),
159 TIMER_OF_DECLARE(sc9860_timer
, "sprd,sc9860-timer", sprd_timer_init
);