- Prioritize the ARM architected timer on Exynos platform when the
architecture is ARM64 (Will Deacon) - Mark the Exynos timer as a per CPU timer (Will Deacon) - DT conversion to yaml for the rockchip platform (Ezequiel Garcia) - Fix IRQ setup if there are two channels on the sh_cmt timer (Phong Hoang) - Use bitfield helper macros in the Ingenic timer (Zhou Yanjie) - Clear any pending interrupt to prevent an abort of the suspend on the Mediatek platform (Fengquan Chen) - Add DT bindings for new Ingenic SoCs (Zhou Yanjie) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEGn3N4YVz0WNVyHskqDIjiipP6E8FAmEkjt8ACgkQqDIjiipP 6E8SHQf+IEw7wShuwZdKB3mPvLX/bjXymcPd7HRq++StxWRv9jwQd/CO0Xk27LT/ J5yiTju1J3dnGY5b8Qxx+cfC3ikI2Iej26H0XBe5y1u8XYBSbKZVdiKGvTYPdAD9 HoYBcCPK2qR0R6qtkzRAVfMTj2Nw7/sjROCMifAhr8QPu1NBgf4XRRvIDd0JKhua oLg8f/5Lo8CFiPJF9LY2Fy58UWBQoCKBp70vO9iPt9BmJca6/SZBLbmyx+yivaEQ /sqFS8+l0B/N48U62BDJ9UJeobeL1VcSGtrZ9dCJ5GMr43aFSSNPOqNJzl8yxYNg PJZFmR1zOXzG8Ldu+wwdNdBAPQQ4AA== =xRl+ -----END PGP SIGNATURE----- Merge tag 'timers-v5.15' of https://git.linaro.org/people/daniel.lezcano/linux into timers/core Pull timer driver updates from Daniel Lezcano: - Prioritize the ARM architected timer on Exynos platform when the architecture is ARM64 (Will Deacon) - Mark the Exynos timer as a per CPU timer (Will Deacon) - DT conversion to yaml for the rockchip platform (Ezequiel Garcia) - Fix IRQ setup if there are two channels on the sh_cmt timer (Phong Hoang) - Use bitfield helper macros in the Ingenic timer (Zhou Yanjie) - Clear any pending interrupt to prevent an abort of the suspend on the Mediatek platform (Fengquan Chen) - Add DT bindings for new Ingenic SoCs (Zhou Yanjie) Link: https://lore.kernel.org/r/c14ad27a-b1c6-6043-0f5e-71dd984bb4ba@linaro.org
This commit is contained in:
commit
127c92feb7
@ -1,27 +0,0 @@
|
||||
Rockchip rk timer
|
||||
|
||||
Required properties:
|
||||
- compatible: should be:
|
||||
"rockchip,rv1108-timer", "rockchip,rk3288-timer": for Rockchip RV1108
|
||||
"rockchip,rk3036-timer", "rockchip,rk3288-timer": for Rockchip RK3036
|
||||
"rockchip,rk3066-timer", "rockchip,rk3288-timer": for Rockchip RK3066
|
||||
"rockchip,rk3188-timer", "rockchip,rk3288-timer": for Rockchip RK3188
|
||||
"rockchip,rk3228-timer", "rockchip,rk3288-timer": for Rockchip RK3228
|
||||
"rockchip,rk3229-timer", "rockchip,rk3288-timer": for Rockchip RK3229
|
||||
"rockchip,rk3288-timer": for Rockchip RK3288
|
||||
"rockchip,rk3368-timer", "rockchip,rk3288-timer": for Rockchip RK3368
|
||||
"rockchip,rk3399-timer": for Rockchip RK3399
|
||||
- reg: base address of the timer register starting with TIMERS CONTROL register
|
||||
- interrupts: should contain the interrupts for Timer0
|
||||
- clocks : must contain an entry for each entry in clock-names
|
||||
- clock-names : must include the following entries:
|
||||
"timer", "pclk"
|
||||
|
||||
Example:
|
||||
timer: timer@ff810000 {
|
||||
compatible = "rockchip,rk3288-timer";
|
||||
reg = <0xff810000 0x20>;
|
||||
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&xin24m>, <&cru PCLK_TIMER>;
|
||||
clock-names = "timer", "pclk";
|
||||
};
|
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/timer/rockchip,rk-timer.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip Timer Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,rk3288-timer
|
||||
- const: rockchip,rk3399-timer
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rv1108-timer
|
||||
- rockchip,rk3036-timer
|
||||
- rockchip,rk3066-timer
|
||||
- rockchip,rk3188-timer
|
||||
- rockchip,rk3228-timer
|
||||
- rockchip,rk3229-timer
|
||||
- rockchip,rk3288-timer
|
||||
- rockchip,rk3368-timer
|
||||
- rockchip,px30-timer
|
||||
- const: rockchip,rk3288-timer
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: timer
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/rk3288-cru.h>
|
||||
|
||||
timer: timer@ff810000 {
|
||||
compatible = "rockchip,rk3288-timer";
|
||||
reg = <0xff810000 0x20>;
|
||||
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru PCLK_TIMER>, <&xin24m>;
|
||||
clock-names = "pclk", "timer";
|
||||
};
|
@ -51,6 +51,15 @@
|
||||
|
||||
#define TICK_BASE_CNT 1
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
/* Use values higher than ARM arch timer. See 6282edb72bed. */
|
||||
#define MCT_CLKSOURCE_RATING 450
|
||||
#define MCT_CLKEVENTS_RATING 500
|
||||
#else
|
||||
#define MCT_CLKSOURCE_RATING 350
|
||||
#define MCT_CLKEVENTS_RATING 350
|
||||
#endif
|
||||
|
||||
enum {
|
||||
MCT_INT_SPI,
|
||||
MCT_INT_PPI
|
||||
@ -206,7 +215,7 @@ static void exynos4_frc_resume(struct clocksource *cs)
|
||||
|
||||
static struct clocksource mct_frc = {
|
||||
.name = "mct-frc",
|
||||
.rating = 450, /* use value higher than ARM arch timer */
|
||||
.rating = MCT_CLKSOURCE_RATING,
|
||||
.read = exynos4_frc_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
@ -456,8 +465,9 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
|
||||
evt->set_state_oneshot = set_state_shutdown;
|
||||
evt->set_state_oneshot_stopped = set_state_shutdown;
|
||||
evt->tick_resume = set_state_shutdown;
|
||||
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
evt->rating = 500; /* use value higher than ARM arch timer */
|
||||
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERCPU;
|
||||
evt->rating = MCT_CLKEVENTS_RATING,
|
||||
|
||||
exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
@ -34,8 +35,6 @@
|
||||
/* bits within the OSTCCR register */
|
||||
#define OSTCCR_PRESCALE1_MASK 0x3
|
||||
#define OSTCCR_PRESCALE2_MASK 0xc
|
||||
#define OSTCCR_PRESCALE1_LSB 0
|
||||
#define OSTCCR_PRESCALE2_LSB 2
|
||||
|
||||
/* bits within the OSTCR register */
|
||||
#define OSTCR_OST1CLR BIT(0)
|
||||
@ -98,7 +97,7 @@ static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw *hw,
|
||||
|
||||
prescale = readl(ost_clk->ost->base + info->ostccr_reg);
|
||||
|
||||
prescale = (prescale & OSTCCR_PRESCALE1_MASK) >> OSTCCR_PRESCALE1_LSB;
|
||||
prescale = FIELD_GET(OSTCCR_PRESCALE1_MASK, prescale);
|
||||
|
||||
return parent_rate >> (prescale * 2);
|
||||
}
|
||||
@ -112,7 +111,7 @@ static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw *hw,
|
||||
|
||||
prescale = readl(ost_clk->ost->base + info->ostccr_reg);
|
||||
|
||||
prescale = (prescale & OSTCCR_PRESCALE2_MASK) >> OSTCCR_PRESCALE2_LSB;
|
||||
prescale = FIELD_GET(OSTCCR_PRESCALE2_MASK, prescale);
|
||||
|
||||
return parent_rate >> (prescale * 2);
|
||||
}
|
||||
@ -151,7 +150,8 @@ static int ingenic_ost_percpu_timer_set_rate(struct clk_hw *hw, unsigned long re
|
||||
int val;
|
||||
|
||||
val = readl(ost_clk->ost->base + info->ostccr_reg);
|
||||
val = (val & ~OSTCCR_PRESCALE1_MASK) | (prescale << OSTCCR_PRESCALE1_LSB);
|
||||
val &= ~OSTCCR_PRESCALE1_MASK;
|
||||
val |= FIELD_PREP(OSTCCR_PRESCALE1_MASK, prescale);
|
||||
writel(val, ost_clk->ost->base + info->ostccr_reg);
|
||||
|
||||
return 0;
|
||||
@ -166,7 +166,8 @@ static int ingenic_ost_global_timer_set_rate(struct clk_hw *hw, unsigned long re
|
||||
int val;
|
||||
|
||||
val = readl(ost_clk->ost->base + info->ostccr_reg);
|
||||
val = (val & ~OSTCCR_PRESCALE2_MASK) | (prescale << OSTCCR_PRESCALE2_LSB);
|
||||
val &= ~OSTCCR_PRESCALE2_MASK;
|
||||
val |= FIELD_PREP(OSTCCR_PRESCALE2_MASK, prescale);
|
||||
writel(val, ost_clk->ost->base + info->ostccr_reg);
|
||||
|
||||
return 0;
|
||||
|
@ -579,7 +579,8 @@ static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag)
|
||||
ch->flags |= flag;
|
||||
|
||||
/* setup timeout if no clockevent */
|
||||
if ((flag == FLAG_CLOCKSOURCE) && (!(ch->flags & FLAG_CLOCKEVENT)))
|
||||
if (ch->cmt->num_channels == 1 &&
|
||||
flag == FLAG_CLOCKSOURCE && (!(ch->flags & FLAG_CLOCKEVENT)))
|
||||
__sh_cmt_set_next(ch, ch->max_match_value);
|
||||
out:
|
||||
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
||||
@ -621,20 +622,25 @@ static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
|
||||
static u64 sh_cmt_clocksource_read(struct clocksource *cs)
|
||||
{
|
||||
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
|
||||
unsigned long flags;
|
||||
u32 has_wrapped;
|
||||
u64 value;
|
||||
u32 raw;
|
||||
|
||||
raw_spin_lock_irqsave(&ch->lock, flags);
|
||||
value = ch->total_cycles;
|
||||
raw = sh_cmt_get_counter(ch, &has_wrapped);
|
||||
if (ch->cmt->num_channels == 1) {
|
||||
unsigned long flags;
|
||||
u64 value;
|
||||
u32 raw;
|
||||
|
||||
if (unlikely(has_wrapped))
|
||||
raw += ch->match_value + 1;
|
||||
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
||||
raw_spin_lock_irqsave(&ch->lock, flags);
|
||||
value = ch->total_cycles;
|
||||
raw = sh_cmt_get_counter(ch, &has_wrapped);
|
||||
|
||||
return value + raw;
|
||||
if (unlikely(has_wrapped))
|
||||
raw += ch->match_value + 1;
|
||||
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
||||
|
||||
return value + raw;
|
||||
}
|
||||
|
||||
return sh_cmt_get_counter(ch, &has_wrapped);
|
||||
}
|
||||
|
||||
static int sh_cmt_clocksource_enable(struct clocksource *cs)
|
||||
@ -697,7 +703,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
|
||||
cs->disable = sh_cmt_clocksource_disable;
|
||||
cs->suspend = sh_cmt_clocksource_suspend;
|
||||
cs->resume = sh_cmt_clocksource_resume;
|
||||
cs->mask = CLOCKSOURCE_MASK(sizeof(u64) * 8);
|
||||
cs->mask = CLOCKSOURCE_MASK(ch->cmt->info->width);
|
||||
cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
|
||||
|
||||
dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n",
|
||||
|
@ -271,9 +271,7 @@ static irqreturn_t ast2600_timer_interrupt(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
static int __init fttmr010_common_init(struct device_node *np,
|
||||
bool is_aspeed,
|
||||
int (*timer_shutdown)(struct clock_event_device *),
|
||||
irq_handler_t irq_handler)
|
||||
bool is_aspeed, bool is_ast2600)
|
||||
{
|
||||
struct fttmr010 *fttmr010;
|
||||
int irq;
|
||||
@ -374,8 +372,6 @@ static int __init fttmr010_common_init(struct device_node *np,
|
||||
fttmr010->tick_rate);
|
||||
}
|
||||
|
||||
fttmr010->timer_shutdown = timer_shutdown;
|
||||
|
||||
/*
|
||||
* Setup clockevent timer (interrupt-driven) on timer 1.
|
||||
*/
|
||||
@ -383,8 +379,18 @@ static int __init fttmr010_common_init(struct device_node *np,
|
||||
writel(0, fttmr010->base + TIMER1_LOAD);
|
||||
writel(0, fttmr010->base + TIMER1_MATCH1);
|
||||
writel(0, fttmr010->base + TIMER1_MATCH2);
|
||||
ret = request_irq(irq, irq_handler, IRQF_TIMER,
|
||||
"FTTMR010-TIMER1", &fttmr010->clkevt);
|
||||
|
||||
if (is_ast2600) {
|
||||
fttmr010->timer_shutdown = ast2600_timer_shutdown;
|
||||
ret = request_irq(irq, ast2600_timer_interrupt,
|
||||
IRQF_TIMER, "FTTMR010-TIMER1",
|
||||
&fttmr010->clkevt);
|
||||
} else {
|
||||
fttmr010->timer_shutdown = fttmr010_timer_shutdown;
|
||||
ret = request_irq(irq, fttmr010_timer_interrupt,
|
||||
IRQF_TIMER, "FTTMR010-TIMER1",
|
||||
&fttmr010->clkevt);
|
||||
}
|
||||
if (ret) {
|
||||
pr_err("FTTMR010-TIMER1 no IRQ\n");
|
||||
goto out_unmap;
|
||||
@ -432,23 +438,17 @@ out_disable_clock:
|
||||
|
||||
static __init int ast2600_timer_init(struct device_node *np)
|
||||
{
|
||||
return fttmr010_common_init(np, true,
|
||||
ast2600_timer_shutdown,
|
||||
ast2600_timer_interrupt);
|
||||
return fttmr010_common_init(np, true, true);
|
||||
}
|
||||
|
||||
static __init int aspeed_timer_init(struct device_node *np)
|
||||
{
|
||||
return fttmr010_common_init(np, true,
|
||||
fttmr010_timer_shutdown,
|
||||
fttmr010_timer_interrupt);
|
||||
return fttmr010_common_init(np, true, false);
|
||||
}
|
||||
|
||||
static __init int fttmr010_timer_init(struct device_node *np)
|
||||
{
|
||||
return fttmr010_common_init(np, false,
|
||||
fttmr010_timer_shutdown,
|
||||
fttmr010_timer_interrupt);
|
||||
return fttmr010_common_init(np, false, false);
|
||||
}
|
||||
|
||||
TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
|
||||
|
@ -60,9 +60,9 @@
|
||||
* SYST_CON_EN: Clock enable. Shall be set to
|
||||
* - Start timer countdown.
|
||||
* - Allow timeout ticks being updated.
|
||||
* - Allow changing interrupt functions.
|
||||
* - Allow changing interrupt status,like clear irq pending.
|
||||
*
|
||||
* SYST_CON_IRQ_EN: Set to allow interrupt.
|
||||
* SYST_CON_IRQ_EN: Set to enable interrupt.
|
||||
*
|
||||
* SYST_CON_IRQ_CLR: Set to clear interrupt.
|
||||
*/
|
||||
@ -75,6 +75,7 @@ static void __iomem *gpt_sched_reg __read_mostly;
|
||||
static void mtk_syst_ack_irq(struct timer_of *to)
|
||||
{
|
||||
/* Clear and disable interrupt */
|
||||
writel(SYST_CON_EN, SYST_CON_REG(to));
|
||||
writel(SYST_CON_IRQ_CLR | SYST_CON_EN, SYST_CON_REG(to));
|
||||
}
|
||||
|
||||
@ -111,6 +112,9 @@ static int mtk_syst_clkevt_next_event(unsigned long ticks,
|
||||
|
||||
static int mtk_syst_clkevt_shutdown(struct clock_event_device *clkevt)
|
||||
{
|
||||
/* Clear any irq */
|
||||
mtk_syst_ack_irq(to_timer_of(clkevt));
|
||||
|
||||
/* Disable timer */
|
||||
writel(0, SYST_CON_REG(to_timer_of(clkevt)));
|
||||
|
||||
|
@ -13,4 +13,23 @@
|
||||
#define OST_CLK_PERCPU_TIMER2 3
|
||||
#define OST_CLK_PERCPU_TIMER3 4
|
||||
|
||||
#define OST_CLK_EVENT_TIMER 1
|
||||
|
||||
#define OST_CLK_EVENT_TIMER0 0
|
||||
#define OST_CLK_EVENT_TIMER1 1
|
||||
#define OST_CLK_EVENT_TIMER2 2
|
||||
#define OST_CLK_EVENT_TIMER3 3
|
||||
#define OST_CLK_EVENT_TIMER4 4
|
||||
#define OST_CLK_EVENT_TIMER5 5
|
||||
#define OST_CLK_EVENT_TIMER6 6
|
||||
#define OST_CLK_EVENT_TIMER7 7
|
||||
#define OST_CLK_EVENT_TIMER8 8
|
||||
#define OST_CLK_EVENT_TIMER9 9
|
||||
#define OST_CLK_EVENT_TIMER10 10
|
||||
#define OST_CLK_EVENT_TIMER11 11
|
||||
#define OST_CLK_EVENT_TIMER12 12
|
||||
#define OST_CLK_EVENT_TIMER13 13
|
||||
#define OST_CLK_EVENT_TIMER14 14
|
||||
#define OST_CLK_EVENT_TIMER15 15
|
||||
|
||||
#endif /* __DT_BINDINGS_CLOCK_INGENIC_OST_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user