Skip to content

Commit a13f950

Browse files
committed
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull clocksource updates from Ingo Molnar: "Misc clocksource/clockevent driver updates that came in a bit late but are ready for v5.2" * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: misc: atmel_tclib: Do not probe already used TCBs clocksource/drivers/timer-atmel-tcb: Convert tc_clksrc_suspend|resume() to static clocksource/drivers/tcb_clksrc: Rename the file for consistency clocksource/drivers/timer-atmel-pit: Rework Kconfig option clocksource/drivers/tcb_clksrc: Move Kconfig option ARM: at91: Implement clocksource selection clocksource/drivers/tcb_clksrc: Use tcb as sched_clock clocksource/drivers/tcb_clksrc: Stop depending on atmel_tclib ARM: at91: move SoC specific definitions to SoC folder clocksource/drivers/timer-milbeaut: Cleanup common register accesses clocksource/drivers/timer-milbeaut: Add shutdown function clocksource/drivers/timer-milbeaut: Fix to enable one-shot timer clocksource/drivers/tegra: Rework for compensation of suspend time clocksource/drivers/sp804: Add COMPILE_TEST to CONFIG_ARM_TIMER_SP804 clocksource/drivers/sun4i: Add a compatible for suniv dt-bindings: timer: Add Allwinner suniv timer
2 parents d9351ea + ea7a5f9 commit a13f950

File tree

12 files changed

+202
-136
lines changed

12 files changed

+202
-136
lines changed

Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ Allwinner A1X SoCs Timer Controller
22

33
Required properties:
44

5-
- compatible : should be "allwinner,sun4i-a10-timer"
5+
- compatible : should be one of the following:
6+
"allwinner,sun4i-a10-timer"
7+
"allwinner,suniv-f1c100s-timer"
68
- reg : Specifies base physical address and size of the registers.
79
- interrupts : The interrupt of the first timer
810
- clocks: phandle to the source clock (usually a 24 MHz fixed clock)

arch/arm/mach-at91/Kconfig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,29 @@ config SOC_AT91SAM9
104104
AT91SAM9X35
105105
AT91SAM9XE
106106

107+
comment "Clocksource driver selection"
108+
109+
config ATMEL_CLOCKSOURCE_PIT
110+
bool "Periodic Interval Timer (PIT) support"
111+
depends on SOC_AT91SAM9 || SOC_SAMA5
112+
default SOC_AT91SAM9 || SOC_SAMA5
113+
select ATMEL_PIT
114+
help
115+
Select this to get a clocksource based on the Atmel Periodic Interval
116+
Timer. It has a relatively low resolution and the TC Block clocksource
117+
should be preferred.
118+
119+
config ATMEL_CLOCKSOURCE_TCB
120+
bool "Timer Counter Blocks (TCB) support"
121+
default SOC_AT91RM9200 || SOC_AT91SAM9 || SOC_SAMA5
122+
select ATMEL_TCB_CLKSRC
123+
help
124+
Select this to get a high precision clocksource based on a
125+
TC block with a 5+ MHz base clock rate.
126+
On platforms with 16-bit counters, two timer channels are combined
127+
to make a single 32-bit timer.
128+
It can also be used as a clock event device supporting oneshot mode.
129+
107130
config HAVE_AT91_UTMI
108131
bool
109132

drivers/clocksource/Kconfig

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ config ARM_GLOBAL_TIMER
387387
This options enables support for the ARM global timer unit
388388

389389
config ARM_TIMER_SP804
390-
bool "Support for Dual Timer SP804 module"
390+
bool "Support for Dual Timer SP804 module" if COMPILE_TEST
391391
depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP
392392
select CLKSRC_MMIO
393393
select TIMER_OF if OF
@@ -407,8 +407,11 @@ config ARMV7M_SYSTICK
407407
This options enables support for the ARMv7M system timer unit
408408

409409
config ATMEL_PIT
410+
bool "Atmel PIT support" if COMPILE_TEST
411+
depends on HAS_IOMEM
410412
select TIMER_OF if OF
411-
def_bool SOC_AT91SAM9 || SOC_SAMA5
413+
help
414+
Support for the Periodic Interval Timer found on Atmel SoCs.
412415

413416
config ATMEL_ST
414417
bool "Atmel ST timer support" if COMPILE_TEST
@@ -418,6 +421,13 @@ config ATMEL_ST
418421
help
419422
Support for the Atmel ST timer.
420423

424+
config ATMEL_TCB_CLKSRC
425+
bool "Atmel TC Block timer driver" if COMPILE_TEST
426+
depends on HAS_IOMEM
427+
select TIMER_OF if OF
428+
help
429+
Support for Timer Counter Blocks on Atmel SoCs.
430+
421431
config CLKSRC_EXYNOS_MCT
422432
bool "Exynos multi core timer driver" if COMPILE_TEST
423433
depends on ARM || ARM64

drivers/clocksource/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ obj-$(CONFIG_TIMER_OF) += timer-of.o
33
obj-$(CONFIG_TIMER_PROBE) += timer-probe.o
44
obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
55
obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
6-
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
6+
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += timer-atmel-tcb.o
77
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
88
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
99
obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += timer-cs5535.o

drivers/clocksource/tcb_clksrc.c renamed to drivers/clocksource/timer-atmel-tcb.c

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
#include <linux/err.h>
1010
#include <linux/ioport.h>
1111
#include <linux/io.h>
12-
#include <linux/platform_device.h>
12+
#include <linux/of_address.h>
13+
#include <linux/of_irq.h>
14+
#include <linux/sched_clock.h>
1315
#include <linux/syscore_ops.h>
14-
#include <linux/atmel_tc.h>
16+
#include <soc/at91/atmel_tcb.h>
1517

1618

1719
/*
@@ -28,13 +30,6 @@
2830
* source, used in either periodic or oneshot mode. This runs
2931
* at 32 KiHZ, and can handle delays of up to two seconds.
3032
*
31-
* A boot clocksource and clockevent source are also currently needed,
32-
* unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
33-
* this code can be used when init_timers() is called, well before most
34-
* devices are set up. (Some low end AT91 parts, which can run uClinux,
35-
* have only the timers in one TC block... they currently don't support
36-
* the tclib code, because of that initialization issue.)
37-
*
3833
* REVISIT behavior during system suspend states... we should disable
3934
* all clocks and save the power. Easily done for clockevent devices,
4035
* but clocksources won't necessarily get the needed notifications.
@@ -112,7 +107,6 @@ static void tc_clksrc_resume(struct clocksource *cs)
112107
}
113108

114109
static struct clocksource clksrc = {
115-
.name = "tcb_clksrc",
116110
.rating = 200,
117111
.read = tc_get_cycles,
118112
.mask = CLOCKSOURCE_MASK(32),
@@ -121,6 +115,16 @@ static struct clocksource clksrc = {
121115
.resume = tc_clksrc_resume,
122116
};
123117

118+
static u64 notrace tc_sched_clock_read(void)
119+
{
120+
return tc_get_cycles(&clksrc);
121+
}
122+
123+
static u64 notrace tc_sched_clock_read32(void)
124+
{
125+
return tc_get_cycles32(&clksrc);
126+
}
127+
124128
#ifdef CONFIG_GENERIC_CLOCKEVENTS
125129

126130
struct tc_clkevt_device {
@@ -214,7 +218,6 @@ static int tc_next_event(unsigned long delta, struct clock_event_device *d)
214218

215219
static struct tc_clkevt_device clkevt = {
216220
.clkevt = {
217-
.name = "tc_clkevt",
218221
.features = CLOCK_EVT_FEAT_PERIODIC |
219222
CLOCK_EVT_FEAT_ONESHOT,
220223
/* Should be lower than at91rm9200's system timer */
@@ -330,39 +333,74 @@ static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_id
330333
writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
331334
}
332335

333-
static int __init tcb_clksrc_init(void)
334-
{
335-
static char bootinfo[] __initdata
336-
= KERN_DEBUG "%s: tc%d at %d.%03d MHz\n";
336+
static const u8 atmel_tcb_divisors[5] = { 2, 8, 32, 128, 0, };
337+
338+
static const struct of_device_id atmel_tcb_of_match[] = {
339+
{ .compatible = "atmel,at91rm9200-tcb", .data = (void *)16, },
340+
{ .compatible = "atmel,at91sam9x5-tcb", .data = (void *)32, },
341+
{ /* sentinel */ }
342+
};
337343

338-
struct platform_device *pdev;
339-
struct atmel_tc *tc;
344+
static int __init tcb_clksrc_init(struct device_node *node)
345+
{
346+
struct atmel_tc tc;
340347
struct clk *t0_clk;
348+
const struct of_device_id *match;
349+
u64 (*tc_sched_clock)(void);
341350
u32 rate, divided_rate = 0;
342351
int best_divisor_idx = -1;
343352
int clk32k_divisor_idx = -1;
353+
int bits;
344354
int i;
345355
int ret;
346356

347-
tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK);
348-
if (!tc) {
349-
pr_debug("can't alloc TC for clocksource\n");
350-
return -ENODEV;
357+
/* Protect against multiple calls */
358+
if (tcaddr)
359+
return 0;
360+
361+
tc.regs = of_iomap(node->parent, 0);
362+
if (!tc.regs)
363+
return -ENXIO;
364+
365+
t0_clk = of_clk_get_by_name(node->parent, "t0_clk");
366+
if (IS_ERR(t0_clk))
367+
return PTR_ERR(t0_clk);
368+
369+
tc.slow_clk = of_clk_get_by_name(node->parent, "slow_clk");
370+
if (IS_ERR(tc.slow_clk))
371+
return PTR_ERR(tc.slow_clk);
372+
373+
tc.clk[0] = t0_clk;
374+
tc.clk[1] = of_clk_get_by_name(node->parent, "t1_clk");
375+
if (IS_ERR(tc.clk[1]))
376+
tc.clk[1] = t0_clk;
377+
tc.clk[2] = of_clk_get_by_name(node->parent, "t2_clk");
378+
if (IS_ERR(tc.clk[2]))
379+
tc.clk[2] = t0_clk;
380+
381+
tc.irq[2] = of_irq_get(node->parent, 2);
382+
if (tc.irq[2] <= 0) {
383+
tc.irq[2] = of_irq_get(node->parent, 0);
384+
if (tc.irq[2] <= 0)
385+
return -EINVAL;
351386
}
352-
tcaddr = tc->regs;
353-
pdev = tc->pdev;
354387

355-
t0_clk = tc->clk[0];
388+
match = of_match_node(atmel_tcb_of_match, node->parent);
389+
bits = (uintptr_t)match->data;
390+
391+
for (i = 0; i < ARRAY_SIZE(tc.irq); i++)
392+
writel(ATMEL_TC_ALL_IRQ, tc.regs + ATMEL_TC_REG(i, IDR));
393+
356394
ret = clk_prepare_enable(t0_clk);
357395
if (ret) {
358396
pr_debug("can't enable T0 clk\n");
359-
goto err_free_tc;
397+
return ret;
360398
}
361399

362400
/* How fast will we be counting? Pick something over 5 MHz. */
363401
rate = (u32) clk_get_rate(t0_clk);
364-
for (i = 0; i < 5; i++) {
365-
unsigned divisor = atmel_tc_divisors[i];
402+
for (i = 0; i < ARRAY_SIZE(atmel_tcb_divisors); i++) {
403+
unsigned divisor = atmel_tcb_divisors[i];
366404
unsigned tmp;
367405

368406
/* remember 32 KiHz clock for later */
@@ -381,27 +419,31 @@ static int __init tcb_clksrc_init(void)
381419
best_divisor_idx = i;
382420
}
383421

384-
385-
printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
386-
divided_rate / 1000000,
422+
clksrc.name = kbasename(node->parent->full_name);
423+
clkevt.clkevt.name = kbasename(node->parent->full_name);
424+
pr_debug("%s at %d.%03d MHz\n", clksrc.name, divided_rate / 1000000,
387425
((divided_rate % 1000000) + 500) / 1000);
388426

389-
if (tc->tcb_config && tc->tcb_config->counter_width == 32) {
427+
tcaddr = tc.regs;
428+
429+
if (bits == 32) {
390430
/* use apropriate function to read 32 bit counter */
391431
clksrc.read = tc_get_cycles32;
392432
/* setup ony channel 0 */
393-
tcb_setup_single_chan(tc, best_divisor_idx);
433+
tcb_setup_single_chan(&tc, best_divisor_idx);
434+
tc_sched_clock = tc_sched_clock_read32;
394435
} else {
395-
/* tclib will give us three clocks no matter what the
436+
/* we have three clocks no matter what the
396437
* underlying platform supports.
397438
*/
398-
ret = clk_prepare_enable(tc->clk[1]);
439+
ret = clk_prepare_enable(tc.clk[1]);
399440
if (ret) {
400441
pr_debug("can't enable T1 clk\n");
401442
goto err_disable_t0;
402443
}
403444
/* setup both channel 0 & 1 */
404-
tcb_setup_dual_chan(tc, best_divisor_idx);
445+
tcb_setup_dual_chan(&tc, best_divisor_idx);
446+
tc_sched_clock = tc_sched_clock_read;
405447
}
406448

407449
/* and away we go! */
@@ -410,24 +452,26 @@ static int __init tcb_clksrc_init(void)
410452
goto err_disable_t1;
411453

412454
/* channel 2: periodic and oneshot timer support */
413-
ret = setup_clkevents(tc, clk32k_divisor_idx);
455+
ret = setup_clkevents(&tc, clk32k_divisor_idx);
414456
if (ret)
415457
goto err_unregister_clksrc;
416458

459+
sched_clock_register(tc_sched_clock, 32, divided_rate);
460+
417461
return 0;
418462

419463
err_unregister_clksrc:
420464
clocksource_unregister(&clksrc);
421465

422466
err_disable_t1:
423-
if (!tc->tcb_config || tc->tcb_config->counter_width != 32)
424-
clk_disable_unprepare(tc->clk[1]);
467+
if (bits != 32)
468+
clk_disable_unprepare(tc.clk[1]);
425469

426470
err_disable_t0:
427471
clk_disable_unprepare(t0_clk);
428472

429-
err_free_tc:
430-
atmel_tc_free(tc);
473+
tcaddr = NULL;
474+
431475
return ret;
432476
}
433-
arch_initcall(tcb_clksrc_init);
477+
TIMER_OF_DECLARE(atmel_tcb_clksrc, "atmel,tcb-timer", tcb_clksrc_init);

0 commit comments

Comments
 (0)