Skip to content

Commit

Permalink
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
 "The timer departement presents:

   - A rather large rework of the hrtimer infrastructure which
     introduces softirq based hrtimers to replace the spread of
     hrtimer/tasklet combos which force the actual callback execution
     into softirq context. The approach is completely different from the
     initial implementation which you cursed at 10 years ago rightfully.

     The softirq based timers have their own queues and there is no
     nasty indirection and list reshuffling in the hard interrupt
     anymore. This comes with conversion of some of the hrtimer/tasklet
     users, the rest and the final removal of that horrible interface
     will come towards the end of the merge window or go through the
     relevant maintainer trees.

     Note: The top commit merged the last minute bugfix for the 10 years
     old CPU hotplug bug as I wanted to make sure that I fatfinger the
     merge conflict resolution myself.

   - The overhaul of the STM32 clocksource/clockevents driver

   - A new driver for the Spreadtrum SC9860 timer

   - A new driver dor the Actions Semi S700 timer

   - The usual set of fixes and updates all over the place"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (53 commits)
  usb/gadget/NCM: Replace tasklet with softirq hrtimer
  ALSA/dummy: Replace tasklet with softirq hrtimer
  hrtimer: Implement SOFT/HARD clock base selection
  hrtimer: Implement support for softirq based hrtimers
  hrtimer: Prepare handling of hard and softirq based hrtimers
  hrtimer: Add clock bases and hrtimer mode for softirq context
  hrtimer: Use irqsave/irqrestore around __run_hrtimer()
  hrtimer: Factor out __hrtimer_next_event_base()
  hrtimer: Factor out __hrtimer_start_range_ns()
  hrtimer: Remove the 'base' parameter from hrtimer_reprogram()
  hrtimer: Make remote enqueue decision less restrictive
  hrtimer: Unify remote enqueue handling
  hrtimer: Unify hrtimer removal handling
  hrtimer: Make hrtimer_force_reprogramm() unconditionally available
  hrtimer: Make hrtimer_reprogramm() unconditional
  hrtimer: Make hrtimer_cpu_base.next_timer handling unconditional
  hrtimer: Make the remote enqueue check unconditional
  hrtimer: Use accesor functions instead of direct access
  hrtimer: Make the hrtimer_cpu_base::hres_active field unconditional, to simplify the code
  hrtimer: Make room in 'struct hrtimer_cpu_base'
  ...
  • Loading branch information
Linus Torvalds committed Jan 30, 2018
2 parents 7bcd342 + 303c146 commit a46d3f9
Show file tree
Hide file tree
Showing 22 changed files with 1,123 additions and 523 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Actions Semi Owl Timer

Required properties:
- compatible : "actions,s500-timer" for S500
"actions,s700-timer" for S700
"actions,s900-timer" for S900
- reg : Offset and length of the register set for the device.
- interrupts : Should contain the interrupts.
Expand Down
20 changes: 20 additions & 0 deletions Documentation/devicetree/bindings/timer/spreadtrum,sprd-timer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Spreadtrum timers

The Spreadtrum SC9860 platform provides 3 general-purpose timers.
These timers can support 32bit or 64bit counter, as well as supporting
period mode or one-shot mode, and they are can be wakeup source
during deep sleep.

Required properties:
- compatible: should be "sprd,sc9860-timer" for SC9860 platform.
- reg: The register address of the timer device.
- interrupts: Should contain the interrupt for the timer device.
- clocks: The phandle to the source clock (usually a 32.768 KHz fixed clock).

Example:
timer@40050000 {
compatible = "sprd,sc9860-timer";
reg = <0 0x40050000 0 0x20>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ext_32k>;
};
8 changes: 8 additions & 0 deletions drivers/clocksource/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ config CLKSRC_STM32
bool "Clocksource for STM32 SoCs" if !ARCH_STM32
depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
select CLKSRC_MMIO
select TIMER_OF

config CLKSRC_MPS2
bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
Expand Down Expand Up @@ -441,6 +442,13 @@ config MTK_TIMER
help
Support for Mediatek timer driver.

config SPRD_TIMER
bool "Spreadtrum timer driver" if COMPILE_TEST
depends on HAS_IOMEM
select TIMER_OF
help
Enables support for the Spreadtrum timer driver.

config SYS_SUPPORTS_SH_MTU2
bool

Expand Down
1 change: 1 addition & 0 deletions drivers/clocksource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
obj-$(CONFIG_OWL_TIMER) += owl-timer.o
obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o

obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
Expand Down
5 changes: 3 additions & 2 deletions drivers/clocksource/owl-timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,6 @@ static int __init owl_timer_init(struct device_node *node)

return 0;
}
CLOCKSOURCE_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init);
CLOCKSOURCE_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init);
TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init);
TIMER_OF_DECLARE(owl_s700, "actions,s700-timer", owl_timer_init);
TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init);
2 changes: 1 addition & 1 deletion drivers/clocksource/tcb_clksrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ static int __init tcb_clksrc_init(void)

printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
divided_rate / 1000000,
((divided_rate + 500000) % 1000000) / 1000);
((divided_rate % 1000000) + 500) / 1000);

if (tc->tcb_config && tc->tcb_config->counter_width == 32) {
/* use apropriate function to read 32 bit counter */
Expand Down
84 changes: 62 additions & 22 deletions drivers/clocksource/timer-of.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@

#include "timer-of.h"

static __init void timer_irq_exit(struct of_timer_irq *of_irq)
/**
* timer_of_irq_exit - Release the interrupt
* @of_irq: an of_timer_irq structure pointer
*
* Free the irq resource
*/
static __init void timer_of_irq_exit(struct of_timer_irq *of_irq)
{
struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);

Expand All @@ -34,8 +40,24 @@ static __init void timer_irq_exit(struct of_timer_irq *of_irq)
free_irq(of_irq->irq, clkevt);
}

static __init int timer_irq_init(struct device_node *np,
struct of_timer_irq *of_irq)
/**
* timer_of_irq_init - Request the interrupt
* @np: a device tree node pointer
* @of_irq: an of_timer_irq structure pointer
*
* Get the interrupt number from the DT from its definition and
* request it. The interrupt is gotten by falling back the following way:
*
* - Get interrupt number by name
* - Get interrupt number by index
*
* When the interrupt is per CPU, 'request_percpu_irq()' is called,
* otherwise 'request_irq()' is used.
*
* Returns 0 on success, < 0 otherwise
*/
static __init int timer_of_irq_init(struct device_node *np,
struct of_timer_irq *of_irq)
{
int ret;
struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
Expand Down Expand Up @@ -72,15 +94,30 @@ static __init int timer_irq_init(struct device_node *np,
return 0;
}

static __init void timer_clk_exit(struct of_timer_clk *of_clk)
/**
* timer_of_clk_exit - Release the clock resources
* @of_clk: a of_timer_clk structure pointer
*
* Disables and releases the refcount on the clk
*/
static __init void timer_of_clk_exit(struct of_timer_clk *of_clk)
{
of_clk->rate = 0;
clk_disable_unprepare(of_clk->clk);
clk_put(of_clk->clk);
}

static __init int timer_clk_init(struct device_node *np,
struct of_timer_clk *of_clk)
/**
* timer_of_clk_init - Initialize the clock resources
* @np: a device tree node pointer
* @of_clk: a of_timer_clk structure pointer
*
* Get the clock by name or by index, enable it and get the rate
*
* Returns 0 on success, < 0 otherwise
*/
static __init int timer_of_clk_init(struct device_node *np,
struct of_timer_clk *of_clk)
{
int ret;

Expand Down Expand Up @@ -116,19 +153,19 @@ static __init int timer_clk_init(struct device_node *np,
goto out;
}

static __init void timer_base_exit(struct of_timer_base *of_base)
static __init void timer_of_base_exit(struct of_timer_base *of_base)
{
iounmap(of_base->base);
}

static __init int timer_base_init(struct device_node *np,
struct of_timer_base *of_base)
static __init int timer_of_base_init(struct device_node *np,
struct of_timer_base *of_base)
{
const char *name = of_base->name ? of_base->name : np->full_name;

of_base->base = of_io_request_and_map(np, of_base->index, name);
of_base->base = of_base->name ?
of_io_request_and_map(np, of_base->index, of_base->name) :
of_iomap(np, of_base->index);
if (IS_ERR(of_base->base)) {
pr_err("Failed to iomap (%s)\n", name);
pr_err("Failed to iomap (%s)\n", of_base->name);
return PTR_ERR(of_base->base);
}

Expand All @@ -141,39 +178,42 @@ int __init timer_of_init(struct device_node *np, struct timer_of *to)
int flags = 0;

if (to->flags & TIMER_OF_BASE) {
ret = timer_base_init(np, &to->of_base);
ret = timer_of_base_init(np, &to->of_base);
if (ret)
goto out_fail;
flags |= TIMER_OF_BASE;
}

if (to->flags & TIMER_OF_CLOCK) {
ret = timer_clk_init(np, &to->of_clk);
ret = timer_of_clk_init(np, &to->of_clk);
if (ret)
goto out_fail;
flags |= TIMER_OF_CLOCK;
}

if (to->flags & TIMER_OF_IRQ) {
ret = timer_irq_init(np, &to->of_irq);
ret = timer_of_irq_init(np, &to->of_irq);
if (ret)
goto out_fail;
flags |= TIMER_OF_IRQ;
}

if (!to->clkevt.name)
to->clkevt.name = np->name;

to->np = np;

return ret;

out_fail:
if (flags & TIMER_OF_IRQ)
timer_irq_exit(&to->of_irq);
timer_of_irq_exit(&to->of_irq);

if (flags & TIMER_OF_CLOCK)
timer_clk_exit(&to->of_clk);
timer_of_clk_exit(&to->of_clk);

if (flags & TIMER_OF_BASE)
timer_base_exit(&to->of_base);
timer_of_base_exit(&to->of_base);
return ret;
}

Expand All @@ -187,11 +227,11 @@ int __init timer_of_init(struct device_node *np, struct timer_of *to)
void __init timer_of_cleanup(struct timer_of *to)
{
if (to->flags & TIMER_OF_IRQ)
timer_irq_exit(&to->of_irq);
timer_of_irq_exit(&to->of_irq);

if (to->flags & TIMER_OF_CLOCK)
timer_clk_exit(&to->of_clk);
timer_of_clk_exit(&to->of_clk);

if (to->flags & TIMER_OF_BASE)
timer_base_exit(&to->of_base);
timer_of_base_exit(&to->of_base);
}
1 change: 1 addition & 0 deletions drivers/clocksource/timer-of.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct of_timer_clk {

struct timer_of {
unsigned int flags;
struct device_node *np;
struct clock_event_device clkevt;
struct of_timer_base of_base;
struct of_timer_irq of_irq;
Expand Down
Loading

0 comments on commit a46d3f9

Please sign in to comment.