diff options
Diffstat (limited to 'drivers/clocksource')
| -rw-r--r-- | drivers/clocksource/Kconfig | 48 | ||||
| -rw-r--r-- | drivers/clocksource/Makefile | 2 | ||||
| -rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 1 | ||||
| -rw-r--r-- | drivers/clocksource/cadence_ttc_timer.c | 121 | ||||
| -rw-r--r-- | drivers/clocksource/exynos_mct.c | 2 | ||||
| -rw-r--r-- | drivers/clocksource/sun4i_timer.c | 2 | ||||
| -rw-r--r-- | drivers/clocksource/time-armada-370-xp.c | 12 | ||||
| -rw-r--r-- | drivers/clocksource/time-orion.c | 28 | ||||
| -rw-r--r-- | drivers/clocksource/timer-keystone.c | 241 | ||||
| -rw-r--r-- | drivers/clocksource/timer-u300.c | 447 |
10 files changed, 841 insertions, 63 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cd6950fd8caf..52e9329e3c51 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
| @@ -140,3 +140,51 @@ config VF_PIT_TIMER | |||
| 140 | bool | 140 | bool |
| 141 | help | 141 | help |
| 142 | Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. | 142 | Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. |
| 143 | |||
| 144 | config SYS_SUPPORTS_SH_CMT | ||
| 145 | bool | ||
| 146 | |||
| 147 | config SYS_SUPPORTS_SH_MTU2 | ||
| 148 | bool | ||
| 149 | |||
| 150 | config SYS_SUPPORTS_SH_TMU | ||
| 151 | bool | ||
| 152 | |||
| 153 | config SYS_SUPPORTS_EM_STI | ||
| 154 | bool | ||
| 155 | |||
| 156 | config SH_TIMER_CMT | ||
| 157 | bool "Renesas CMT timer driver" if COMPILE_TEST | ||
| 158 | depends on GENERIC_CLOCKEVENTS | ||
| 159 | default SYS_SUPPORTS_SH_CMT | ||
| 160 | help | ||
| 161 | This enables build of a clocksource and clockevent driver for | ||
| 162 | the Compare Match Timer (CMT) hardware available in 16/32/48-bit | ||
| 163 | variants on a wide range of Mobile and Automotive SoCs from Renesas. | ||
| 164 | |||
| 165 | config SH_TIMER_MTU2 | ||
| 166 | bool "Renesas MTU2 timer driver" if COMPILE_TEST | ||
| 167 | depends on GENERIC_CLOCKEVENTS | ||
| 168 | default SYS_SUPPORTS_SH_MTU2 | ||
| 169 | help | ||
| 170 | This enables build of a clockevent driver for the Multi-Function | ||
| 171 | Timer Pulse Unit 2 (TMU2) hardware available on SoCs from Renesas. | ||
| 172 | This hardware comes with 16 bit-timer registers. | ||
| 173 | |||
| 174 | config SH_TIMER_TMU | ||
| 175 | bool "Renesas TMU timer driver" if COMPILE_TEST | ||
| 176 | depends on GENERIC_CLOCKEVENTS | ||
| 177 | default SYS_SUPPORTS_SH_TMU | ||
| 178 | help | ||
| 179 | This enables build of a clocksource and clockevent driver for | ||
| 180 | the 32-bit Timer Unit (TMU) hardware available on a wide range | ||
| 181 | SoCs from Renesas. | ||
| 182 | |||
| 183 | config EM_TIMER_STI | ||
| 184 | bool "Renesas STI timer driver" if COMPILE_TEST | ||
| 185 | depends on GENERIC_CLOCKEVENTS | ||
| 186 | default SYS_SUPPORTS_EM_STI | ||
| 187 | help | ||
| 188 | This enables build of a clocksource and clockevent driver for | ||
| 189 | the 48-bit System Timer (STI) hardware available on a SoCs | ||
| 190 | such as EMEV2 from former NEC Electronics. | ||
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index c7ca50a9c232..aed3488d9426 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
| @@ -21,6 +21,7 @@ obj-$(CONFIG_ARCH_MARCO) += timer-marco.o | |||
| 21 | obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o | 21 | obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o |
| 22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o | 22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o |
| 23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o | 23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o |
| 24 | obj-$(CONFIG_ARCH_U300) += timer-u300.o | ||
| 24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 25 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
| 25 | obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o | 26 | obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o |
| 26 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 27 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o |
| @@ -37,3 +38,4 @@ obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o | |||
| 37 | obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o | 38 | obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o |
| 38 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o | 39 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o |
| 39 | obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o | 40 | obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o |
| 41 | obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o | ||
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 95fb944e15ee..57e823c44d2a 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
| @@ -277,6 +277,7 @@ static void __arch_timer_setup(unsigned type, | |||
| 277 | clk->set_next_event = arch_timer_set_next_event_phys; | 277 | clk->set_next_event = arch_timer_set_next_event_phys; |
| 278 | } | 278 | } |
| 279 | } else { | 279 | } else { |
| 280 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; | ||
| 280 | clk->name = "arch_mem_timer"; | 281 | clk->name = "arch_mem_timer"; |
| 281 | clk->rating = 400; | 282 | clk->rating = 400; |
| 282 | clk->cpumask = cpu_all_mask; | 283 | clk->cpumask = cpu_all_mask; |
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 63f176de0d02..49fbe2847c84 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
| 19 | #include <linux/clk-provider.h> | ||
| 19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 20 | #include <linux/clockchips.h> | 21 | #include <linux/clockchips.h> |
| 21 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
| @@ -52,6 +53,8 @@ | |||
| 52 | #define TTC_CNT_CNTRL_DISABLE_MASK 0x1 | 53 | #define TTC_CNT_CNTRL_DISABLE_MASK 0x1 |
| 53 | 54 | ||
| 54 | #define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ | 55 | #define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ |
| 56 | #define TTC_CLK_CNTRL_PSV_MASK 0x1e | ||
| 57 | #define TTC_CLK_CNTRL_PSV_SHIFT 1 | ||
| 55 | 58 | ||
| 56 | /* | 59 | /* |
| 57 | * Setup the timers to use pre-scaling, using a fixed value for now that will | 60 | * Setup the timers to use pre-scaling, using a fixed value for now that will |
| @@ -63,6 +66,8 @@ | |||
| 63 | #define CLK_CNTRL_PRESCALE_EN 1 | 66 | #define CLK_CNTRL_PRESCALE_EN 1 |
| 64 | #define CNT_CNTRL_RESET (1 << 4) | 67 | #define CNT_CNTRL_RESET (1 << 4) |
| 65 | 68 | ||
| 69 | #define MAX_F_ERR 50 | ||
| 70 | |||
| 66 | /** | 71 | /** |
| 67 | * struct ttc_timer - This definition defines local timer structure | 72 | * struct ttc_timer - This definition defines local timer structure |
| 68 | * | 73 | * |
| @@ -82,6 +87,8 @@ struct ttc_timer { | |||
| 82 | container_of(x, struct ttc_timer, clk_rate_change_nb) | 87 | container_of(x, struct ttc_timer, clk_rate_change_nb) |
| 83 | 88 | ||
| 84 | struct ttc_timer_clocksource { | 89 | struct ttc_timer_clocksource { |
| 90 | u32 scale_clk_ctrl_reg_old; | ||
| 91 | u32 scale_clk_ctrl_reg_new; | ||
| 85 | struct ttc_timer ttc; | 92 | struct ttc_timer ttc; |
| 86 | struct clocksource cs; | 93 | struct clocksource cs; |
| 87 | }; | 94 | }; |
| @@ -229,32 +236,89 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, | |||
| 229 | struct ttc_timer_clocksource, ttc); | 236 | struct ttc_timer_clocksource, ttc); |
| 230 | 237 | ||
| 231 | switch (event) { | 238 | switch (event) { |
| 232 | case POST_RATE_CHANGE: | 239 | case PRE_RATE_CHANGE: |
| 240 | { | ||
| 241 | u32 psv; | ||
| 242 | unsigned long factor, rate_low, rate_high; | ||
| 243 | |||
| 244 | if (ndata->new_rate > ndata->old_rate) { | ||
| 245 | factor = DIV_ROUND_CLOSEST(ndata->new_rate, | ||
| 246 | ndata->old_rate); | ||
| 247 | rate_low = ndata->old_rate; | ||
| 248 | rate_high = ndata->new_rate; | ||
| 249 | } else { | ||
| 250 | factor = DIV_ROUND_CLOSEST(ndata->old_rate, | ||
| 251 | ndata->new_rate); | ||
| 252 | rate_low = ndata->new_rate; | ||
| 253 | rate_high = ndata->old_rate; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (!is_power_of_2(factor)) | ||
| 257 | return NOTIFY_BAD; | ||
| 258 | |||
| 259 | if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR) | ||
| 260 | return NOTIFY_BAD; | ||
| 261 | |||
| 262 | factor = __ilog2_u32(factor); | ||
| 263 | |||
| 233 | /* | 264 | /* |
| 234 | * Do whatever is necessary to maintain a proper time base | 265 | * store timer clock ctrl register so we can restore it in case |
| 235 | * | 266 | * of an abort. |
| 236 | * I cannot find a way to adjust the currently used clocksource | ||
| 237 | * to the new frequency. __clocksource_updatefreq_hz() sounds | ||
| 238 | * good, but does not work. Not sure what's that missing. | ||
| 239 | * | ||
| 240 | * This approach works, but triggers two clocksource switches. | ||
| 241 | * The first after unregister to clocksource jiffies. And | ||
| 242 | * another one after the register to the newly registered timer. | ||
| 243 | * | ||
| 244 | * Alternatively we could 'waste' another HW timer to ping pong | ||
| 245 | * between clock sources. That would also use one register and | ||
| 246 | * one unregister call, but only trigger one clocksource switch | ||
| 247 | * for the cost of another HW timer used by the OS. | ||
| 248 | */ | 267 | */ |
| 249 | clocksource_unregister(&ttccs->cs); | 268 | ttccs->scale_clk_ctrl_reg_old = |
| 250 | clocksource_register_hz(&ttccs->cs, | 269 | __raw_readl(ttccs->ttc.base_addr + |
| 251 | ndata->new_rate / PRESCALE); | 270 | TTC_CLK_CNTRL_OFFSET); |
| 252 | /* fall through */ | 271 | |
| 253 | case PRE_RATE_CHANGE: | 272 | psv = (ttccs->scale_clk_ctrl_reg_old & |
| 273 | TTC_CLK_CNTRL_PSV_MASK) >> | ||
| 274 | TTC_CLK_CNTRL_PSV_SHIFT; | ||
| 275 | if (ndata->new_rate < ndata->old_rate) | ||
| 276 | psv -= factor; | ||
| 277 | else | ||
| 278 | psv += factor; | ||
| 279 | |||
| 280 | /* prescaler within legal range? */ | ||
| 281 | if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT)) | ||
| 282 | return NOTIFY_BAD; | ||
| 283 | |||
| 284 | ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old & | ||
| 285 | ~TTC_CLK_CNTRL_PSV_MASK; | ||
| 286 | ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT; | ||
| 287 | |||
| 288 | |||
| 289 | /* scale down: adjust divider in post-change notification */ | ||
| 290 | if (ndata->new_rate < ndata->old_rate) | ||
| 291 | return NOTIFY_DONE; | ||
| 292 | |||
| 293 | /* scale up: adjust divider now - before frequency change */ | ||
| 294 | __raw_writel(ttccs->scale_clk_ctrl_reg_new, | ||
| 295 | ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | case POST_RATE_CHANGE: | ||
| 299 | /* scale up: pre-change notification did the adjustment */ | ||
| 300 | if (ndata->new_rate > ndata->old_rate) | ||
| 301 | return NOTIFY_OK; | ||
| 302 | |||
| 303 | /* scale down: adjust divider now - after frequency change */ | ||
| 304 | __raw_writel(ttccs->scale_clk_ctrl_reg_new, | ||
| 305 | ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
| 306 | break; | ||
| 307 | |||
| 254 | case ABORT_RATE_CHANGE: | 308 | case ABORT_RATE_CHANGE: |
| 309 | /* we have to undo the adjustment in case we scale up */ | ||
| 310 | if (ndata->new_rate < ndata->old_rate) | ||
| 311 | return NOTIFY_OK; | ||
| 312 | |||
| 313 | /* restore original register value */ | ||
| 314 | __raw_writel(ttccs->scale_clk_ctrl_reg_old, | ||
| 315 | ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
| 316 | /* fall through */ | ||
| 255 | default: | 317 | default: |
| 256 | return NOTIFY_DONE; | 318 | return NOTIFY_DONE; |
| 257 | } | 319 | } |
| 320 | |||
| 321 | return NOTIFY_DONE; | ||
| 258 | } | 322 | } |
| 259 | 323 | ||
| 260 | static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) | 324 | static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) |
| @@ -321,25 +385,12 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | |||
| 321 | 385 | ||
| 322 | switch (event) { | 386 | switch (event) { |
| 323 | case POST_RATE_CHANGE: | 387 | case POST_RATE_CHANGE: |
| 324 | { | ||
| 325 | unsigned long flags; | ||
| 326 | |||
| 327 | /* | ||
| 328 | * clockevents_update_freq should be called with IRQ disabled on | ||
| 329 | * the CPU the timer provides events for. The timer we use is | ||
| 330 | * common to both CPUs, not sure if we need to run on both | ||
| 331 | * cores. | ||
| 332 | */ | ||
| 333 | local_irq_save(flags); | ||
| 334 | clockevents_update_freq(&ttcce->ce, | ||
| 335 | ndata->new_rate / PRESCALE); | ||
| 336 | local_irq_restore(flags); | ||
| 337 | |||
| 338 | /* update cached frequency */ | 388 | /* update cached frequency */ |
| 339 | ttc->freq = ndata->new_rate; | 389 | ttc->freq = ndata->new_rate; |
| 340 | 390 | ||
| 391 | clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); | ||
| 392 | |||
| 341 | /* fall through */ | 393 | /* fall through */ |
| 342 | } | ||
| 343 | case PRE_RATE_CHANGE: | 394 | case PRE_RATE_CHANGE: |
| 344 | case ABORT_RATE_CHANGE: | 395 | case ABORT_RATE_CHANGE: |
| 345 | default: | 396 | default: |
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 48f76bc05da0..c2e390efbdca 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c | |||
| @@ -410,7 +410,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) | |||
| 410 | mevt = container_of(evt, struct mct_clock_event_device, evt); | 410 | mevt = container_of(evt, struct mct_clock_event_device, evt); |
| 411 | 411 | ||
| 412 | mevt->base = EXYNOS4_MCT_L_BASE(cpu); | 412 | mevt->base = EXYNOS4_MCT_L_BASE(cpu); |
| 413 | sprintf(mevt->name, "mct_tick%d", cpu); | 413 | snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu); |
| 414 | 414 | ||
| 415 | evt->name = mevt->name; | 415 | evt->name = mevt->name; |
| 416 | evt->cpumask = cpumask_of(cpu); | 416 | evt->cpumask = cpumask_of(cpu); |
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index bf497afba9ad..efb17c3ee120 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c | |||
| @@ -196,5 +196,5 @@ static void __init sun4i_timer_init(struct device_node *node) | |||
| 196 | clockevents_config_and_register(&sun4i_clockevent, rate, | 196 | clockevents_config_and_register(&sun4i_clockevent, rate, |
| 197 | TIMER_SYNC_TICKS, 0xffffffff); | 197 | TIMER_SYNC_TICKS, 0xffffffff); |
| 198 | } | 198 | } |
| 199 | CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", | 199 | CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", |
| 200 | sun4i_timer_init); | 200 | sun4i_timer_init); |
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index ee8691b89944..0451e62fac7a 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c | |||
| @@ -85,12 +85,6 @@ static u32 ticks_per_jiffy; | |||
| 85 | 85 | ||
| 86 | static struct clock_event_device __percpu *armada_370_xp_evt; | 86 | static struct clock_event_device __percpu *armada_370_xp_evt; |
| 87 | 87 | ||
| 88 | static void timer_ctrl_clrset(u32 clr, u32 set) | ||
| 89 | { | ||
| 90 | writel((readl(timer_base + TIMER_CTRL_OFF) & ~clr) | set, | ||
| 91 | timer_base + TIMER_CTRL_OFF); | ||
| 92 | } | ||
| 93 | |||
| 94 | static void local_timer_ctrl_clrset(u32 clr, u32 set) | 88 | static void local_timer_ctrl_clrset(u32 clr, u32 set) |
| 95 | { | 89 | { |
| 96 | writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, | 90 | writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, |
| @@ -245,7 +239,7 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) | |||
| 245 | clr = TIMER0_25MHZ; | 239 | clr = TIMER0_25MHZ; |
| 246 | enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); | 240 | enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); |
| 247 | } | 241 | } |
| 248 | timer_ctrl_clrset(clr, set); | 242 | atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set); |
| 249 | local_timer_ctrl_clrset(clr, set); | 243 | local_timer_ctrl_clrset(clr, set); |
| 250 | 244 | ||
| 251 | /* | 245 | /* |
| @@ -263,7 +257,9 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) | |||
| 263 | writel(0xffffffff, timer_base + TIMER0_VAL_OFF); | 257 | writel(0xffffffff, timer_base + TIMER0_VAL_OFF); |
| 264 | writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); | 258 | writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); |
| 265 | 259 | ||
| 266 | timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); | 260 | atomic_io_modify(timer_base + TIMER_CTRL_OFF, |
| 261 | TIMER0_RELOAD_EN | enable_mask, | ||
| 262 | TIMER0_RELOAD_EN | enable_mask); | ||
| 267 | 263 | ||
| 268 | /* | 264 | /* |
| 269 | * Set scale and timer for sched_clock. | 265 | * Set scale and timer for sched_clock. |
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 20066222f3f2..0b3ce0399c51 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c | |||
| @@ -35,20 +35,6 @@ | |||
| 35 | #define ORION_ONESHOT_MAX 0xfffffffe | 35 | #define ORION_ONESHOT_MAX 0xfffffffe |
| 36 | 36 | ||
| 37 | static void __iomem *timer_base; | 37 | static void __iomem *timer_base; |
| 38 | static DEFINE_SPINLOCK(timer_ctrl_lock); | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Thread-safe access to TIMER_CTRL register | ||
| 42 | * (shared with watchdog timer) | ||
| 43 | */ | ||
| 44 | void orion_timer_ctrl_clrset(u32 clr, u32 set) | ||
| 45 | { | ||
| 46 | spin_lock(&timer_ctrl_lock); | ||
| 47 | writel((readl(timer_base + TIMER_CTRL) & ~clr) | set, | ||
| 48 | timer_base + TIMER_CTRL); | ||
| 49 | spin_unlock(&timer_ctrl_lock); | ||
| 50 | } | ||
| 51 | EXPORT_SYMBOL(orion_timer_ctrl_clrset); | ||
| 52 | 38 | ||
| 53 | /* | 39 | /* |
| 54 | * Free-running clocksource handling. | 40 | * Free-running clocksource handling. |
| @@ -68,7 +54,8 @@ static int orion_clkevt_next_event(unsigned long delta, | |||
| 68 | { | 54 | { |
| 69 | /* setup and enable one-shot timer */ | 55 | /* setup and enable one-shot timer */ |
| 70 | writel(delta, timer_base + TIMER1_VAL); | 56 | writel(delta, timer_base + TIMER1_VAL); |
| 71 | orion_timer_ctrl_clrset(TIMER1_RELOAD_EN, TIMER1_EN); | 57 | atomic_io_modify(timer_base + TIMER_CTRL, |
| 58 | TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN); | ||
| 72 | 59 | ||
| 73 | return 0; | 60 | return 0; |
| 74 | } | 61 | } |
| @@ -80,10 +67,13 @@ static void orion_clkevt_mode(enum clock_event_mode mode, | |||
| 80 | /* setup and enable periodic timer at 1/HZ intervals */ | 67 | /* setup and enable periodic timer at 1/HZ intervals */ |
| 81 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); | 68 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); |
| 82 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); | 69 | writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); |
| 83 | orion_timer_ctrl_clrset(0, TIMER1_RELOAD_EN | TIMER1_EN); | 70 | atomic_io_modify(timer_base + TIMER_CTRL, |
| 71 | TIMER1_RELOAD_EN | TIMER1_EN, | ||
| 72 | TIMER1_RELOAD_EN | TIMER1_EN); | ||
| 84 | } else { | 73 | } else { |
| 85 | /* disable timer */ | 74 | /* disable timer */ |
| 86 | orion_timer_ctrl_clrset(TIMER1_RELOAD_EN | TIMER1_EN, 0); | 75 | atomic_io_modify(timer_base + TIMER_CTRL, |
| 76 | TIMER1_RELOAD_EN | TIMER1_EN, 0); | ||
| 87 | } | 77 | } |
| 88 | } | 78 | } |
| 89 | 79 | ||
| @@ -131,7 +121,9 @@ static void __init orion_timer_init(struct device_node *np) | |||
| 131 | /* setup timer0 as free-running clocksource */ | 121 | /* setup timer0 as free-running clocksource */ |
| 132 | writel(~0, timer_base + TIMER0_VAL); | 122 | writel(~0, timer_base + TIMER0_VAL); |
| 133 | writel(~0, timer_base + TIMER0_RELOAD); | 123 | writel(~0, timer_base + TIMER0_RELOAD); |
| 134 | orion_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | TIMER0_EN); | 124 | atomic_io_modify(timer_base + TIMER_CTRL, |
| 125 | TIMER0_RELOAD_EN | TIMER0_EN, | ||
| 126 | TIMER0_RELOAD_EN | TIMER0_EN); | ||
| 135 | clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", | 127 | clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", |
| 136 | clk_get_rate(clk), 300, 32, | 128 | clk_get_rate(clk), 300, 32, |
| 137 | clocksource_mmio_readl_down); | 129 | clocksource_mmio_readl_down); |
diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c new file mode 100644 index 000000000000..0250354f7e55 --- /dev/null +++ b/drivers/clocksource/timer-keystone.c | |||
| @@ -0,0 +1,241 @@ | |||
| 1 | /* | ||
| 2 | * Keystone broadcast clock-event | ||
| 3 | * | ||
| 4 | * Copyright 2013 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/clk.h> | ||
| 15 | #include <linux/clockchips.h> | ||
| 16 | #include <linux/clocksource.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/of_address.h> | ||
| 19 | #include <linux/of_irq.h> | ||
| 20 | |||
| 21 | #define TIMER_NAME "timer-keystone" | ||
| 22 | |||
| 23 | /* Timer register offsets */ | ||
| 24 | #define TIM12 0x10 | ||
| 25 | #define TIM34 0x14 | ||
| 26 | #define PRD12 0x18 | ||
| 27 | #define PRD34 0x1c | ||
| 28 | #define TCR 0x20 | ||
| 29 | #define TGCR 0x24 | ||
| 30 | #define INTCTLSTAT 0x44 | ||
| 31 | |||
| 32 | /* Timer register bitfields */ | ||
| 33 | #define TCR_ENAMODE_MASK 0xC0 | ||
| 34 | #define TCR_ENAMODE_ONESHOT_MASK 0x40 | ||
| 35 | #define TCR_ENAMODE_PERIODIC_MASK 0x80 | ||
| 36 | |||
| 37 | #define TGCR_TIM_UNRESET_MASK 0x03 | ||
| 38 | #define INTCTLSTAT_ENINT_MASK 0x01 | ||
| 39 | |||
| 40 | /** | ||
| 41 | * struct keystone_timer: holds timer's data | ||
| 42 | * @base: timer memory base address | ||
| 43 | * @hz_period: cycles per HZ period | ||
| 44 | * @event_dev: event device based on timer | ||
| 45 | */ | ||
| 46 | static struct keystone_timer { | ||
| 47 | void __iomem *base; | ||
| 48 | unsigned long hz_period; | ||
| 49 | struct clock_event_device event_dev; | ||
| 50 | } timer; | ||
| 51 | |||
| 52 | static inline u32 keystone_timer_readl(unsigned long rg) | ||
| 53 | { | ||
| 54 | return readl_relaxed(timer.base + rg); | ||
| 55 | } | ||
| 56 | |||
| 57 | static inline void keystone_timer_writel(u32 val, unsigned long rg) | ||
| 58 | { | ||
| 59 | writel_relaxed(val, timer.base + rg); | ||
| 60 | } | ||
| 61 | |||
| 62 | /** | ||
| 63 | * keystone_timer_barrier: write memory barrier | ||
| 64 | * use explicit barrier to avoid using readl/writel non relaxed function | ||
| 65 | * variants, because in our case non relaxed variants hide the true places | ||
| 66 | * where barrier is needed. | ||
| 67 | */ | ||
| 68 | static inline void keystone_timer_barrier(void) | ||
| 69 | { | ||
| 70 | __iowmb(); | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * keystone_timer_config: configures timer to work in oneshot/periodic modes. | ||
| 75 | * @ mode: mode to configure | ||
| 76 | * @ period: cycles number to configure for | ||
| 77 | */ | ||
| 78 | static int keystone_timer_config(u64 period, enum clock_event_mode mode) | ||
| 79 | { | ||
| 80 | u32 tcr; | ||
| 81 | u32 off; | ||
| 82 | |||
| 83 | tcr = keystone_timer_readl(TCR); | ||
| 84 | off = tcr & ~(TCR_ENAMODE_MASK); | ||
| 85 | |||
| 86 | /* set enable mode */ | ||
| 87 | switch (mode) { | ||
| 88 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 89 | tcr |= TCR_ENAMODE_ONESHOT_MASK; | ||
| 90 | break; | ||
| 91 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 92 | tcr |= TCR_ENAMODE_PERIODIC_MASK; | ||
| 93 | break; | ||
| 94 | default: | ||
| 95 | return -1; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* disable timer */ | ||
| 99 | keystone_timer_writel(off, TCR); | ||
| 100 | /* here we have to be sure the timer has been disabled */ | ||
| 101 | keystone_timer_barrier(); | ||
| 102 | |||
| 103 | /* reset counter to zero, set new period */ | ||
| 104 | keystone_timer_writel(0, TIM12); | ||
| 105 | keystone_timer_writel(0, TIM34); | ||
| 106 | keystone_timer_writel(period & 0xffffffff, PRD12); | ||
| 107 | keystone_timer_writel(period >> 32, PRD34); | ||
| 108 | |||
| 109 | /* | ||
| 110 | * enable timer | ||
| 111 | * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers | ||
| 112 | * have been written. | ||
| 113 | */ | ||
| 114 | keystone_timer_barrier(); | ||
| 115 | keystone_timer_writel(tcr, TCR); | ||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | static void keystone_timer_disable(void) | ||
| 120 | { | ||
| 121 | u32 tcr; | ||
| 122 | |||
| 123 | tcr = keystone_timer_readl(TCR); | ||
| 124 | |||
| 125 | /* disable timer */ | ||
| 126 | tcr &= ~(TCR_ENAMODE_MASK); | ||
| 127 | keystone_timer_writel(tcr, TCR); | ||
| 128 | } | ||
| 129 | |||
| 130 | static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id) | ||
| 131 | { | ||
| 132 | struct clock_event_device *evt = dev_id; | ||
| 133 | |||
| 134 | evt->event_handler(evt); | ||
| 135 | return IRQ_HANDLED; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int keystone_set_next_event(unsigned long cycles, | ||
| 139 | struct clock_event_device *evt) | ||
| 140 | { | ||
| 141 | return keystone_timer_config(cycles, evt->mode); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void keystone_set_mode(enum clock_event_mode mode, | ||
| 145 | struct clock_event_device *evt) | ||
| 146 | { | ||
| 147 | switch (mode) { | ||
| 148 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 149 | keystone_timer_config(timer.hz_period, CLOCK_EVT_MODE_PERIODIC); | ||
| 150 | break; | ||
| 151 | case CLOCK_EVT_MODE_UNUSED: | ||
| 152 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 153 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 154 | keystone_timer_disable(); | ||
| 155 | break; | ||
| 156 | default: | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | static void __init keystone_timer_init(struct device_node *np) | ||
| 162 | { | ||
| 163 | struct clock_event_device *event_dev = &timer.event_dev; | ||
| 164 | unsigned long rate; | ||
| 165 | struct clk *clk; | ||
| 166 | int irq, error; | ||
| 167 | |||
| 168 | irq = irq_of_parse_and_map(np, 0); | ||
| 169 | if (irq == NO_IRQ) { | ||
| 170 | pr_err("%s: failed to map interrupts\n", __func__); | ||
| 171 | return; | ||
| 172 | } | ||
| 173 | |||
| 174 | timer.base = of_iomap(np, 0); | ||
| 175 | if (!timer.base) { | ||
| 176 | pr_err("%s: failed to map registers\n", __func__); | ||
| 177 | return; | ||
| 178 | } | ||
| 179 | |||
| 180 | clk = of_clk_get(np, 0); | ||
| 181 | if (IS_ERR(clk)) { | ||
| 182 | pr_err("%s: failed to get clock\n", __func__); | ||
| 183 | iounmap(timer.base); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | error = clk_prepare_enable(clk); | ||
| 188 | if (error) { | ||
| 189 | pr_err("%s: failed to enable clock\n", __func__); | ||
| 190 | goto err; | ||
| 191 | } | ||
| 192 | |||
| 193 | rate = clk_get_rate(clk); | ||
| 194 | |||
| 195 | /* disable, use internal clock source */ | ||
| 196 | keystone_timer_writel(0, TCR); | ||
| 197 | /* here we have to be sure the timer has been disabled */ | ||
| 198 | keystone_timer_barrier(); | ||
| 199 | |||
| 200 | /* reset timer as 64-bit, no pre-scaler, plus features are disabled */ | ||
| 201 | keystone_timer_writel(0, TGCR); | ||
| 202 | |||
| 203 | /* unreset timer */ | ||
| 204 | keystone_timer_writel(TGCR_TIM_UNRESET_MASK, TGCR); | ||
| 205 | |||
| 206 | /* init counter to zero */ | ||
| 207 | keystone_timer_writel(0, TIM12); | ||
| 208 | keystone_timer_writel(0, TIM34); | ||
| 209 | |||
| 210 | timer.hz_period = DIV_ROUND_UP(rate, HZ); | ||
| 211 | |||
| 212 | /* enable timer interrupts */ | ||
| 213 | keystone_timer_writel(INTCTLSTAT_ENINT_MASK, INTCTLSTAT); | ||
| 214 | |||
| 215 | error = request_irq(irq, keystone_timer_interrupt, IRQF_TIMER, | ||
| 216 | TIMER_NAME, event_dev); | ||
| 217 | if (error) { | ||
| 218 | pr_err("%s: failed to setup irq\n", __func__); | ||
| 219 | goto err; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* setup clockevent */ | ||
| 223 | event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | ||
| 224 | event_dev->set_next_event = keystone_set_next_event; | ||
| 225 | event_dev->set_mode = keystone_set_mode; | ||
| 226 | event_dev->cpumask = cpu_all_mask; | ||
| 227 | event_dev->owner = THIS_MODULE; | ||
| 228 | event_dev->name = TIMER_NAME; | ||
| 229 | event_dev->irq = irq; | ||
| 230 | |||
| 231 | clockevents_config_and_register(event_dev, rate, 1, ULONG_MAX); | ||
| 232 | |||
| 233 | pr_info("keystone timer clock @%lu Hz\n", rate); | ||
| 234 | return; | ||
| 235 | err: | ||
| 236 | clk_put(clk); | ||
| 237 | iounmap(timer.base); | ||
| 238 | } | ||
| 239 | |||
| 240 | CLOCKSOURCE_OF_DECLARE(keystone_timer, "ti,keystone-timer", | ||
| 241 | keystone_timer_init); | ||
diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c new file mode 100644 index 000000000000..e63d469661fd --- /dev/null +++ b/drivers/clocksource/timer-u300.c | |||
| @@ -0,0 +1,447 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2009 ST-Ericsson AB | ||
| 3 | * License terms: GNU General Public License (GPL) version 2 | ||
| 4 | * Timer COH 901 328, runs the OS timer interrupt. | ||
| 5 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
| 6 | */ | ||
| 7 | #include <linux/interrupt.h> | ||
| 8 | #include <linux/time.h> | ||
| 9 | #include <linux/timex.h> | ||
| 10 | #include <linux/clockchips.h> | ||
| 11 | #include <linux/clocksource.h> | ||
| 12 | #include <linux/types.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/clk.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/irq.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/of_address.h> | ||
| 19 | #include <linux/of_irq.h> | ||
| 20 | #include <linux/sched_clock.h> | ||
| 21 | |||
| 22 | /* Generic stuff */ | ||
| 23 | #include <asm/mach/map.h> | ||
| 24 | #include <asm/mach/time.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * APP side special timer registers | ||
| 28 | * This timer contains four timers which can fire an interrupt each. | ||
| 29 | * OS (operating system) timer @ 32768 Hz | ||
| 30 | * DD (device driver) timer @ 1 kHz | ||
| 31 | * GP1 (general purpose 1) timer @ 1MHz | ||
| 32 | * GP2 (general purpose 2) timer @ 1MHz | ||
| 33 | */ | ||
| 34 | |||
| 35 | /* Reset OS Timer 32bit (-/W) */ | ||
| 36 | #define U300_TIMER_APP_ROST (0x0000) | ||
| 37 | #define U300_TIMER_APP_ROST_TIMER_RESET (0x00000000) | ||
| 38 | /* Enable OS Timer 32bit (-/W) */ | ||
| 39 | #define U300_TIMER_APP_EOST (0x0004) | ||
| 40 | #define U300_TIMER_APP_EOST_TIMER_ENABLE (0x00000000) | ||
| 41 | /* Disable OS Timer 32bit (-/W) */ | ||
| 42 | #define U300_TIMER_APP_DOST (0x0008) | ||
| 43 | #define U300_TIMER_APP_DOST_TIMER_DISABLE (0x00000000) | ||
| 44 | /* OS Timer Mode Register 32bit (-/W) */ | ||
| 45 | #define U300_TIMER_APP_SOSTM (0x000c) | ||
| 46 | #define U300_TIMER_APP_SOSTM_MODE_CONTINUOUS (0x00000000) | ||
| 47 | #define U300_TIMER_APP_SOSTM_MODE_ONE_SHOT (0x00000001) | ||
| 48 | /* OS Timer Status Register 32bit (R/-) */ | ||
| 49 | #define U300_TIMER_APP_OSTS (0x0010) | ||
| 50 | #define U300_TIMER_APP_OSTS_TIMER_STATE_MASK (0x0000000F) | ||
| 51 | #define U300_TIMER_APP_OSTS_TIMER_STATE_IDLE (0x00000001) | ||
| 52 | #define U300_TIMER_APP_OSTS_TIMER_STATE_ACTIVE (0x00000002) | ||
| 53 | #define U300_TIMER_APP_OSTS_ENABLE_IND (0x00000010) | ||
| 54 | #define U300_TIMER_APP_OSTS_MODE_MASK (0x00000020) | ||
| 55 | #define U300_TIMER_APP_OSTS_MODE_CONTINUOUS (0x00000000) | ||
| 56 | #define U300_TIMER_APP_OSTS_MODE_ONE_SHOT (0x00000020) | ||
| 57 | #define U300_TIMER_APP_OSTS_IRQ_ENABLED_IND (0x00000040) | ||
| 58 | #define U300_TIMER_APP_OSTS_IRQ_PENDING_IND (0x00000080) | ||
| 59 | /* OS Timer Current Count Register 32bit (R/-) */ | ||
| 60 | #define U300_TIMER_APP_OSTCC (0x0014) | ||
| 61 | /* OS Timer Terminal Count Register 32bit (R/W) */ | ||
| 62 | #define U300_TIMER_APP_OSTTC (0x0018) | ||
| 63 | /* OS Timer Interrupt Enable Register 32bit (-/W) */ | ||
| 64 | #define U300_TIMER_APP_OSTIE (0x001c) | ||
| 65 | #define U300_TIMER_APP_OSTIE_IRQ_DISABLE (0x00000000) | ||
| 66 | #define U300_TIMER_APP_OSTIE_IRQ_ENABLE (0x00000001) | ||
| 67 | /* OS Timer Interrupt Acknowledge Register 32bit (-/W) */ | ||
| 68 | #define U300_TIMER_APP_OSTIA (0x0020) | ||
| 69 | #define U300_TIMER_APP_OSTIA_IRQ_ACK (0x00000080) | ||
| 70 | |||
| 71 | /* Reset DD Timer 32bit (-/W) */ | ||
| 72 | #define U300_TIMER_APP_RDDT (0x0040) | ||
| 73 | #define U300_TIMER_APP_RDDT_TIMER_RESET (0x00000000) | ||
| 74 | /* Enable DD Timer 32bit (-/W) */ | ||
| 75 | #define U300_TIMER_APP_EDDT (0x0044) | ||
| 76 | #define U300_TIMER_APP_EDDT_TIMER_ENABLE (0x00000000) | ||
| 77 | /* Disable DD Timer 32bit (-/W) */ | ||
| 78 | #define U300_TIMER_APP_DDDT (0x0048) | ||
| 79 | #define U300_TIMER_APP_DDDT_TIMER_DISABLE (0x00000000) | ||
| 80 | /* DD Timer Mode Register 32bit (-/W) */ | ||
| 81 | #define U300_TIMER_APP_SDDTM (0x004c) | ||
| 82 | #define U300_TIMER_APP_SDDTM_MODE_CONTINUOUS (0x00000000) | ||
| 83 | #define U300_TIMER_APP_SDDTM_MODE_ONE_SHOT (0x00000001) | ||
| 84 | /* DD Timer Status Register 32bit (R/-) */ | ||
| 85 | #define U300_TIMER_APP_DDTS (0x0050) | ||
| 86 | #define U300_TIMER_APP_DDTS_TIMER_STATE_MASK (0x0000000F) | ||
| 87 | #define U300_TIMER_APP_DDTS_TIMER_STATE_IDLE (0x00000001) | ||
| 88 | #define U300_TIMER_APP_DDTS_TIMER_STATE_ACTIVE (0x00000002) | ||
| 89 | #define U300_TIMER_APP_DDTS_ENABLE_IND (0x00000010) | ||
| 90 | #define U300_TIMER_APP_DDTS_MODE_MASK (0x00000020) | ||
| 91 | #define U300_TIMER_APP_DDTS_MODE_CONTINUOUS (0x00000000) | ||
| 92 | #define U300_TIMER_APP_DDTS_MODE_ONE_SHOT (0x00000020) | ||
| 93 | #define U300_TIMER_APP_DDTS_IRQ_ENABLED_IND (0x00000040) | ||
| 94 | #define U300_TIMER_APP_DDTS_IRQ_PENDING_IND (0x00000080) | ||
| 95 | /* DD Timer Current Count Register 32bit (R/-) */ | ||
| 96 | #define U300_TIMER_APP_DDTCC (0x0054) | ||
| 97 | /* DD Timer Terminal Count Register 32bit (R/W) */ | ||
| 98 | #define U300_TIMER_APP_DDTTC (0x0058) | ||
| 99 | /* DD Timer Interrupt Enable Register 32bit (-/W) */ | ||
| 100 | #define U300_TIMER_APP_DDTIE (0x005c) | ||
| 101 | #define U300_TIMER_APP_DDTIE_IRQ_DISABLE (0x00000000) | ||
| 102 | #define U300_TIMER_APP_DDTIE_IRQ_ENABLE (0x00000001) | ||
| 103 | /* DD Timer Interrupt Acknowledge Register 32bit (-/W) */ | ||
| 104 | #define U300_TIMER_APP_DDTIA (0x0060) | ||
| 105 | #define U300_TIMER_APP_DDTIA_IRQ_ACK (0x00000080) | ||
| 106 | |||
| 107 | /* Reset GP1 Timer 32bit (-/W) */ | ||
| 108 | #define U300_TIMER_APP_RGPT1 (0x0080) | ||
| 109 | #define U300_TIMER_APP_RGPT1_TIMER_RESET (0x00000000) | ||
| 110 | /* Enable GP1 Timer 32bit (-/W) */ | ||
| 111 | #define U300_TIMER_APP_EGPT1 (0x0084) | ||
| 112 | #define U300_TIMER_APP_EGPT1_TIMER_ENABLE (0x00000000) | ||
| 113 | /* Disable GP1 Timer 32bit (-/W) */ | ||
| 114 | #define U300_TIMER_APP_DGPT1 (0x0088) | ||
| 115 | #define U300_TIMER_APP_DGPT1_TIMER_DISABLE (0x00000000) | ||
| 116 | /* GP1 Timer Mode Register 32bit (-/W) */ | ||
| 117 | #define U300_TIMER_APP_SGPT1M (0x008c) | ||
| 118 | #define U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS (0x00000000) | ||
| 119 | #define U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT (0x00000001) | ||
| 120 | /* GP1 Timer Status Register 32bit (R/-) */ | ||
| 121 | #define U300_TIMER_APP_GPT1S (0x0090) | ||
| 122 | #define U300_TIMER_APP_GPT1S_TIMER_STATE_MASK (0x0000000F) | ||
| 123 | #define U300_TIMER_APP_GPT1S_TIMER_STATE_IDLE (0x00000001) | ||
| 124 | #define U300_TIMER_APP_GPT1S_TIMER_STATE_ACTIVE (0x00000002) | ||
| 125 | #define U300_TIMER_APP_GPT1S_ENABLE_IND (0x00000010) | ||
| 126 | #define U300_TIMER_APP_GPT1S_MODE_MASK (0x00000020) | ||
| 127 | #define U300_TIMER_APP_GPT1S_MODE_CONTINUOUS (0x00000000) | ||
| 128 | #define U300_TIMER_APP_GPT1S_MODE_ONE_SHOT (0x00000020) | ||
| 129 | #define U300_TIMER_APP_GPT1S_IRQ_ENABLED_IND (0x00000040) | ||
| 130 | #define U300_TIMER_APP_GPT1S_IRQ_PENDING_IND (0x00000080) | ||
| 131 | /* GP1 Timer Current Count Register 32bit (R/-) */ | ||
| 132 | #define U300_TIMER_APP_GPT1CC (0x0094) | ||
| 133 | /* GP1 Timer Terminal Count Register 32bit (R/W) */ | ||
| 134 | #define U300_TIMER_APP_GPT1TC (0x0098) | ||
| 135 | /* GP1 Timer Interrupt Enable Register 32bit (-/W) */ | ||
| 136 | #define U300_TIMER_APP_GPT1IE (0x009c) | ||
| 137 | #define U300_TIMER_APP_GPT1IE_IRQ_DISABLE (0x00000000) | ||
| 138 | #define U300_TIMER_APP_GPT1IE_IRQ_ENABLE (0x00000001) | ||
| 139 | /* GP1 Timer Interrupt Acknowledge Register 32bit (-/W) */ | ||
| 140 | #define U300_TIMER_APP_GPT1IA (0x00a0) | ||
| 141 | #define U300_TIMER_APP_GPT1IA_IRQ_ACK (0x00000080) | ||
| 142 | |||
| 143 | /* Reset GP2 Timer 32bit (-/W) */ | ||
| 144 | #define U300_TIMER_APP_RGPT2 (0x00c0) | ||
| 145 | #define U300_TIMER_APP_RGPT2_TIMER_RESET (0x00000000) | ||
| 146 | /* Enable GP2 Timer 32bit (-/W) */ | ||
| 147 | #define U300_TIMER_APP_EGPT2 (0x00c4) | ||
| 148 | #define U300_TIMER_APP_EGPT2_TIMER_ENABLE (0x00000000) | ||
| 149 | /* Disable GP2 Timer 32bit (-/W) */ | ||
| 150 | #define U300_TIMER_APP_DGPT2 (0x00c8) | ||
| 151 | #define U300_TIMER_APP_DGPT2_TIMER_DISABLE (0x00000000) | ||
| 152 | /* GP2 Timer Mode Register 32bit (-/W) */ | ||
| 153 | #define U300_TIMER_APP_SGPT2M (0x00cc) | ||
| 154 | #define U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS (0x00000000) | ||
| 155 | #define U300_TIMER_APP_SGPT2M_MODE_ONE_SHOT (0x00000001) | ||
| 156 | /* GP2 Timer Status Register 32bit (R/-) */ | ||
| 157 | #define U300_TIMER_APP_GPT2S (0x00d0) | ||
| 158 | #define U300_TIMER_APP_GPT2S_TIMER_STATE_MASK (0x0000000F) | ||
| 159 | #define U300_TIMER_APP_GPT2S_TIMER_STATE_IDLE (0x00000001) | ||
| 160 | #define U300_TIMER_APP_GPT2S_TIMER_STATE_ACTIVE (0x00000002) | ||
| 161 | #define U300_TIMER_APP_GPT2S_ENABLE_IND (0x00000010) | ||
| 162 | #define U300_TIMER_APP_GPT2S_MODE_MASK (0x00000020) | ||
| 163 | #define U300_TIMER_APP_GPT2S_MODE_CONTINUOUS (0x00000000) | ||
| 164 | #define U300_TIMER_APP_GPT2S_MODE_ONE_SHOT (0x00000020) | ||
| 165 | #define U300_TIMER_APP_GPT2S_IRQ_ENABLED_IND (0x00000040) | ||
| 166 | #define U300_TIMER_APP_GPT2S_IRQ_PENDING_IND (0x00000080) | ||
| 167 | /* GP2 Timer Current Count Register 32bit (R/-) */ | ||
| 168 | #define U300_TIMER_APP_GPT2CC (0x00d4) | ||
| 169 | /* GP2 Timer Terminal Count Register 32bit (R/W) */ | ||
| 170 | #define U300_TIMER_APP_GPT2TC (0x00d8) | ||
| 171 | /* GP2 Timer Interrupt Enable Register 32bit (-/W) */ | ||
| 172 | #define U300_TIMER_APP_GPT2IE (0x00dc) | ||
| 173 | #define U300_TIMER_APP_GPT2IE_IRQ_DISABLE (0x00000000) | ||
| 174 | #define U300_TIMER_APP_GPT2IE_IRQ_ENABLE (0x00000001) | ||
| 175 | /* GP2 Timer Interrupt Acknowledge Register 32bit (-/W) */ | ||
| 176 | #define U300_TIMER_APP_GPT2IA (0x00e0) | ||
| 177 | #define U300_TIMER_APP_GPT2IA_IRQ_ACK (0x00000080) | ||
| 178 | |||
| 179 | /* Clock request control register - all four timers */ | ||
| 180 | #define U300_TIMER_APP_CRC (0x100) | ||
| 181 | #define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE (0x00000001) | ||
| 182 | |||
| 183 | static void __iomem *u300_timer_base; | ||
| 184 | |||
| 185 | struct u300_clockevent_data { | ||
| 186 | struct clock_event_device cevd; | ||
| 187 | unsigned ticks_per_jiffy; | ||
| 188 | }; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * The u300_set_mode() function is always called first, if we | ||
| 192 | * have oneshot timer active, the oneshot scheduling function | ||
| 193 | * u300_set_next_event() is called immediately after. | ||
| 194 | */ | ||
| 195 | static void u300_set_mode(enum clock_event_mode mode, | ||
| 196 | struct clock_event_device *evt) | ||
| 197 | { | ||
| 198 | struct u300_clockevent_data *cevdata = | ||
| 199 | container_of(evt, struct u300_clockevent_data, cevd); | ||
| 200 | |||
| 201 | switch (mode) { | ||
| 202 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 203 | /* Disable interrupts on GPT1 */ | ||
| 204 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
| 205 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 206 | /* Disable GP1 while we're reprogramming it. */ | ||
| 207 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
| 208 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
| 209 | /* | ||
| 210 | * Set the periodic mode to a certain number of ticks per | ||
| 211 | * jiffy. | ||
| 212 | */ | ||
| 213 | writel(cevdata->ticks_per_jiffy, | ||
| 214 | u300_timer_base + U300_TIMER_APP_GPT1TC); | ||
| 215 | /* | ||
| 216 | * Set continuous mode, so the timer keeps triggering | ||
| 217 | * interrupts. | ||
| 218 | */ | ||
| 219 | writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, | ||
| 220 | u300_timer_base + U300_TIMER_APP_SGPT1M); | ||
| 221 | /* Enable timer interrupts */ | ||
| 222 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | ||
| 223 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 224 | /* Then enable the OS timer again */ | ||
| 225 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | ||
| 226 | u300_timer_base + U300_TIMER_APP_EGPT1); | ||
| 227 | break; | ||
| 228 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 229 | /* Just break; here? */ | ||
| 230 | /* | ||
| 231 | * The actual event will be programmed by the next event hook, | ||
| 232 | * so we just set a dummy value somewhere at the end of the | ||
| 233 | * universe here. | ||
| 234 | */ | ||
| 235 | /* Disable interrupts on GPT1 */ | ||
| 236 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
| 237 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 238 | /* Disable GP1 while we're reprogramming it. */ | ||
| 239 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
| 240 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
| 241 | /* | ||
| 242 | * Expire far in the future, u300_set_next_event() will be | ||
| 243 | * called soon... | ||
| 244 | */ | ||
| 245 | writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC); | ||
| 246 | /* We run one shot per tick here! */ | ||
| 247 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, | ||
| 248 | u300_timer_base + U300_TIMER_APP_SGPT1M); | ||
| 249 | /* Enable interrupts for this timer */ | ||
| 250 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | ||
| 251 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 252 | /* Enable timer */ | ||
| 253 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | ||
| 254 | u300_timer_base + U300_TIMER_APP_EGPT1); | ||
| 255 | break; | ||
| 256 | case CLOCK_EVT_MODE_UNUSED: | ||
| 257 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 258 | /* Disable interrupts on GP1 */ | ||
| 259 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
| 260 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 261 | /* Disable GP1 */ | ||
| 262 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
| 263 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
| 264 | break; | ||
| 265 | case CLOCK_EVT_MODE_RESUME: | ||
| 266 | /* Ignore this call */ | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | /* | ||
| 272 | * The app timer in one shot mode obviously has to be reprogrammed | ||
| 273 | * in EXACTLY this sequence to work properly. Do NOT try to e.g. replace | ||
| 274 | * the interrupt disable + timer disable commands with a reset command, | ||
| 275 | * it will fail miserably. Apparently (and I found this the hard way) | ||
| 276 | * the timer is very sensitive to the instruction order, though you don't | ||
| 277 | * get that impression from the data sheet. | ||
| 278 | */ | ||
| 279 | static int u300_set_next_event(unsigned long cycles, | ||
| 280 | struct clock_event_device *evt) | ||
| 281 | |||
| 282 | { | ||
| 283 | /* Disable interrupts on GPT1 */ | ||
| 284 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | ||
| 285 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 286 | /* Disable GP1 while we're reprogramming it. */ | ||
| 287 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | ||
| 288 | u300_timer_base + U300_TIMER_APP_DGPT1); | ||
| 289 | /* Reset the General Purpose timer 1. */ | ||
| 290 | writel(U300_TIMER_APP_RGPT1_TIMER_RESET, | ||
| 291 | u300_timer_base + U300_TIMER_APP_RGPT1); | ||
| 292 | /* IRQ in n * cycles */ | ||
| 293 | writel(cycles, u300_timer_base + U300_TIMER_APP_GPT1TC); | ||
| 294 | /* | ||
| 295 | * We run one shot per tick here! (This is necessary to reconfigure, | ||
| 296 | * the timer will tilt if you don't!) | ||
| 297 | */ | ||
| 298 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, | ||
| 299 | u300_timer_base + U300_TIMER_APP_SGPT1M); | ||
| 300 | /* Enable timer interrupts */ | ||
| 301 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | ||
| 302 | u300_timer_base + U300_TIMER_APP_GPT1IE); | ||
| 303 | /* Then enable the OS timer again */ | ||
| 304 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | ||
| 305 | u300_timer_base + U300_TIMER_APP_EGPT1); | ||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static struct u300_clockevent_data u300_clockevent_data = { | ||
| 310 | /* Use general purpose timer 1 as clock event */ | ||
| 311 | .cevd = { | ||
| 312 | .name = "GPT1", | ||
| 313 | /* Reasonably fast and accurate clock event */ | ||
| 314 | .rating = 300, | ||
| 315 | .features = CLOCK_EVT_FEAT_PERIODIC | | ||
| 316 | CLOCK_EVT_FEAT_ONESHOT, | ||
| 317 | .set_next_event = u300_set_next_event, | ||
| 318 | .set_mode = u300_set_mode, | ||
| 319 | }, | ||
| 320 | }; | ||
| 321 | |||
| 322 | /* Clock event timer interrupt handler */ | ||
| 323 | static irqreturn_t u300_timer_interrupt(int irq, void *dev_id) | ||
| 324 | { | ||
| 325 | struct clock_event_device *evt = &u300_clockevent_data.cevd; | ||
| 326 | /* ACK/Clear timer IRQ for the APP GPT1 Timer */ | ||
| 327 | |||
| 328 | writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, | ||
| 329 | u300_timer_base + U300_TIMER_APP_GPT1IA); | ||
| 330 | evt->event_handler(evt); | ||
| 331 | return IRQ_HANDLED; | ||
| 332 | } | ||
| 333 | |||
| 334 | static struct irqaction u300_timer_irq = { | ||
| 335 | .name = "U300 Timer Tick", | ||
| 336 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
| 337 | .handler = u300_timer_interrupt, | ||
| 338 | }; | ||
| 339 | |||
| 340 | /* | ||
| 341 | * Override the global weak sched_clock symbol with this | ||
| 342 | * local implementation which uses the clocksource to get some | ||
| 343 | * better resolution when scheduling the kernel. We accept that | ||
| 344 | * this wraps around for now, since it is just a relative time | ||
| 345 | * stamp. (Inspired by OMAP implementation.) | ||
| 346 | */ | ||
| 347 | |||
| 348 | static u64 notrace u300_read_sched_clock(void) | ||
| 349 | { | ||
| 350 | return readl(u300_timer_base + U300_TIMER_APP_GPT2CC); | ||
| 351 | } | ||
| 352 | |||
| 353 | static unsigned long u300_read_current_timer(void) | ||
| 354 | { | ||
| 355 | return readl(u300_timer_base + U300_TIMER_APP_GPT2CC); | ||
| 356 | } | ||
| 357 | |||
| 358 | static struct delay_timer u300_delay_timer; | ||
| 359 | |||
| 360 | /* | ||
| 361 | * This sets up the system timers, clock source and clock event. | ||
| 362 | */ | ||
| 363 | static void __init u300_timer_init_of(struct device_node *np) | ||
| 364 | { | ||
| 365 | unsigned int irq; | ||
| 366 | struct clk *clk; | ||
| 367 | unsigned long rate; | ||
| 368 | |||
| 369 | u300_timer_base = of_iomap(np, 0); | ||
| 370 | if (!u300_timer_base) | ||
| 371 | panic("could not ioremap system timer\n"); | ||
| 372 | |||
| 373 | /* Get the IRQ for the GP1 timer */ | ||
| 374 | irq = irq_of_parse_and_map(np, 2); | ||
| 375 | if (!irq) | ||
| 376 | panic("no IRQ for system timer\n"); | ||
| 377 | |||
| 378 | pr_info("U300 GP1 timer @ base: %p, IRQ: %u\n", u300_timer_base, irq); | ||
| 379 | |||
| 380 | /* Clock the interrupt controller */ | ||
| 381 | clk = of_clk_get(np, 0); | ||
| 382 | BUG_ON(IS_ERR(clk)); | ||
| 383 | clk_prepare_enable(clk); | ||
| 384 | rate = clk_get_rate(clk); | ||
| 385 | |||
| 386 | u300_clockevent_data.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); | ||
| 387 | |||
| 388 | sched_clock_register(u300_read_sched_clock, 32, rate); | ||
| 389 | |||
| 390 | u300_delay_timer.read_current_timer = &u300_read_current_timer; | ||
| 391 | u300_delay_timer.freq = rate; | ||
| 392 | register_current_timer_delay(&u300_delay_timer); | ||
| 393 | |||
| 394 | /* | ||
| 395 | * Disable the "OS" and "DD" timers - these are designed for Symbian! | ||
| 396 | * Example usage in cnh1601578 cpu subsystem pd_timer_app.c | ||
| 397 | */ | ||
| 398 | writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE, | ||
| 399 | u300_timer_base + U300_TIMER_APP_CRC); | ||
| 400 | writel(U300_TIMER_APP_ROST_TIMER_RESET, | ||
| 401 | u300_timer_base + U300_TIMER_APP_ROST); | ||
| 402 | writel(U300_TIMER_APP_DOST_TIMER_DISABLE, | ||
| 403 | u300_timer_base + U300_TIMER_APP_DOST); | ||
| 404 | writel(U300_TIMER_APP_RDDT_TIMER_RESET, | ||
| 405 | u300_timer_base + U300_TIMER_APP_RDDT); | ||
| 406 | writel(U300_TIMER_APP_DDDT_TIMER_DISABLE, | ||
| 407 | u300_timer_base + U300_TIMER_APP_DDDT); | ||
| 408 | |||
| 409 | /* Reset the General Purpose timer 1. */ | ||
| 410 | writel(U300_TIMER_APP_RGPT1_TIMER_RESET, | ||
| 411 | u300_timer_base + U300_TIMER_APP_RGPT1); | ||
| 412 | |||
| 413 | /* Set up the IRQ handler */ | ||
| 414 | setup_irq(irq, &u300_timer_irq); | ||
| 415 | |||
| 416 | /* Reset the General Purpose timer 2 */ | ||
| 417 | writel(U300_TIMER_APP_RGPT2_TIMER_RESET, | ||
| 418 | u300_timer_base + U300_TIMER_APP_RGPT2); | ||
| 419 | /* Set this timer to run around forever */ | ||
| 420 | writel(0xFFFFFFFFU, u300_timer_base + U300_TIMER_APP_GPT2TC); | ||
| 421 | /* Set continuous mode so it wraps around */ | ||
| 422 | writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS, | ||
| 423 | u300_timer_base + U300_TIMER_APP_SGPT2M); | ||
| 424 | /* Disable timer interrupts */ | ||
| 425 | writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE, | ||
| 426 | u300_timer_base + U300_TIMER_APP_GPT2IE); | ||
| 427 | /* Then enable the GP2 timer to use as a free running us counter */ | ||
| 428 | writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, | ||
| 429 | u300_timer_base + U300_TIMER_APP_EGPT2); | ||
| 430 | |||
| 431 | /* Use general purpose timer 2 as clock source */ | ||
| 432 | if (clocksource_mmio_init(u300_timer_base + U300_TIMER_APP_GPT2CC, | ||
| 433 | "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) | ||
| 434 | pr_err("timer: failed to initialize U300 clock source\n"); | ||
| 435 | |||
| 436 | /* Configure and register the clockevent */ | ||
| 437 | clockevents_config_and_register(&u300_clockevent_data.cevd, rate, | ||
| 438 | 1, 0xffffffff); | ||
| 439 | |||
| 440 | /* | ||
| 441 | * TODO: init and register the rest of the timers too, they can be | ||
| 442 | * used by hrtimers! | ||
| 443 | */ | ||
| 444 | } | ||
| 445 | |||
| 446 | CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer", | ||
| 447 | u300_timer_init_of); | ||
