Commit 63a3f119 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'timers-core-2023-10-29-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
 "Updates for time, timekeeping and timers:

  Core:

   - Avoid superfluous deactivation of the tick in the low resolution
     tick NOHZ interrupt handler as the deactivation is handled already
     in the idle loop and on interrupt exit.

   - Update stale comments in the tick NOHZ code and rename the tick
     handler functions to be self-explanatory.

   - Remove an unused function in the tick NOHZ code, which was
     forgotten when the last user went away.

   - Handle RTC alarms which exceed the maximum alarm time of the
     underlying RTC hardware gracefully.

     Setting RTC alarms which exceed the maximum alarm time of the RTC
     hardware failed so far and caused suspend operations to abort.

     Cure this by limiting the alarm to the maximum alarm time of the
     RTC hardware, which is provided by the driver. This causes early
     resume wakeups, but that's way better than not suspending at all.

  Drivers:

   - Add a proper clocksource/event driver for the ancient Cirrus Logic
     EP93xx SoC family, which is one of the last non device-tree
     holdouts in arch/arm.

   - The usual boring device tree bindings updates and small fixes and
     enhancements all over the place"

* tag 'timers-core-2023-10-29-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  clocksource: ep93xx: Add driver for Cirrus Logic EP93xx
  dt-bindings: timers: Add Cirrus EP93xx
  clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware
  clocksource/timer-riscv: ACPI: Add timer_cannot_wakeup_cpu
  clocksource/drivers/sun5i: Remove surplus dev_err() when using platform_get_irq()
  drivers/clocksource/timer-ti-dm: Don't call clk_get_rate() in stop function
  clocksource/drivers/timer-imx-gpt: Fix potential memory leak
  dt-bindings: timer: renesas,rz-mtu3: Document RZ/{G2UL,Five} SoCs
  dt-bindings: timer: renesas,rz-mtu3: Improve documentation
  dt-bindings: timer: renesas,rz-mtu3: Fix overflow/underflow interrupt names
  alarmtimer: Use maximum alarm time for suspend
  rtc: Add API function to return alarm time bound by hardware limit
  tick/nohz: Update comments some more
  tick/nohz: Remove unused tick_nohz_idle_stop_tick_protected()
  tick/nohz: Don't shutdown the lowres tick from itself
  tick/nohz: Update obsolete comments
  tick/nohz: Rename the tick handlers to more self-explanatory names
parents c891e98a f4febfdb
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/timer/cirrus,ep9301-timer.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cirrus Logic EP93xx timer
maintainers:
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
- Nikita Shubin <nikita.shubin@maquefel.me>
properties:
compatible:
oneOf:
- const: cirrus,ep9301-timer
- items:
- enum:
- cirrus,ep9302-timer
- cirrus,ep9307-timer
- cirrus,ep9312-timer
- cirrus,ep9315-timer
- const: cirrus,ep9301-timer
reg:
maxItems: 1
interrupts:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
timer@80810000 {
compatible = "cirrus,ep9301-timer";
reg = <0x80810000 0x100>;
interrupt-parent = <&vic1>;
interrupts = <19>;
};
...
...@@ -11,8 +11,8 @@ maintainers: ...@@ -11,8 +11,8 @@ maintainers:
description: | description: |
This hardware block consists of eight 16-bit timer channels and one This hardware block consists of eight 16-bit timer channels and one
32- bit timer channel. It supports the following specifications: 32-bit timer channel. It supports the following specifications:
- Pulse input/output: 28 lines max. - Pulse input/output: 28 lines max
- Pulse input 3 lines - Pulse input 3 lines
- Count clock 11 clocks for each channel (14 clocks for MTU0, 12 clocks - Count clock 11 clocks for each channel (14 clocks for MTU0, 12 clocks
for MTU2, and 10 clocks for MTU5, four clocks for MTU1-MTU2 combination for MTU2, and 10 clocks for MTU5, four clocks for MTU1-MTU2 combination
...@@ -23,11 +23,11 @@ description: | ...@@ -23,11 +23,11 @@ description: |
- Input capture function (noise filter setting available) - Input capture function (noise filter setting available)
- Counter-clearing operation - Counter-clearing operation
- Simultaneous writing to multiple timer counters (TCNT) - Simultaneous writing to multiple timer counters (TCNT)
(excluding MTU8). (excluding MTU8)
- Simultaneous clearing on compare match or input capture - Simultaneous clearing on compare match or input capture
(excluding MTU8). (excluding MTU8)
- Simultaneous input and output to registers in synchronization with - Simultaneous input and output to registers in synchronization with
counter operations (excluding MTU8). counter operations (excluding MTU8)
- Up to 12-phase PWM output in combination with synchronous operation - Up to 12-phase PWM output in combination with synchronous operation
(excluding MTU8) (excluding MTU8)
- [MTU0 MTU3, MTU4, MTU6, MTU7, and MTU8] - [MTU0 MTU3, MTU4, MTU6, MTU7, and MTU8]
...@@ -40,26 +40,26 @@ description: | ...@@ -40,26 +40,26 @@ description: |
- [MTU3, MTU4, MTU6, and MTU7] - [MTU3, MTU4, MTU6, and MTU7]
- Through interlocked operation of MTU3/4 and MTU6/7, the positive and - Through interlocked operation of MTU3/4 and MTU6/7, the positive and
negative signals in six phases (12 phases in total) can be output in negative signals in six phases (12 phases in total) can be output in
complementary PWM and reset-synchronized PWM operation. complementary PWM and reset-synchronized PWM operation
- In complementary PWM mode, values can be transferred from buffer - In complementary PWM mode, values can be transferred from buffer
registers to temporary registers at crests and troughs of the timer- registers to temporary registers at crests and troughs of the timer-
counter values or when the buffer registers (TGRD registers in MTU4 counter values or when the buffer registers (TGRD registers in MTU4
and MTU7) are written to. and MTU7) are written to
- Double-buffering selectable in complementary PWM mode. - Double-buffering selectable in complementary PWM mode
- [MTU3 and MTU4] - [MTU3 and MTU4]
- Through interlocking with MTU0, a mode for driving AC synchronous - Through interlocking with MTU0, a mode for driving AC synchronous
motors (brushless DC motors) by using complementary PWM output and motors (brushless DC motors) by using complementary PWM output and
reset-synchronized PWM output is settable and allows the selection reset-synchronized PWM output is settable and allows the selection
of two types of waveform output (chopping or level). of two types of waveform output (chopping or level)
- [MTU5] - [MTU5]
- Capable of operation as a dead-time compensation counter. - Capable of operation as a dead-time compensation counter
- [MTU0/MTU5, MTU1, MTU2, and MTU8] - [MTU0/MTU5, MTU1, MTU2, and MTU8]
- 32-bit phase counting mode specifiable by combining MTU1 and MTU2 and - 32-bit phase counting mode specifiable by combining MTU1 and MTU2 and
through interlocked operation with MTU0/MTU5 and MTU8. through interlocked operation with MTU0/MTU5 and MTU8
- Interrupt-skipping function - Interrupt-skipping function
- In complementary PWM mode, interrupts on crests and troughs of counter - In complementary PWM mode, interrupts on crests and troughs of counter
values and triggers to start conversion by the A/D converter can be values and triggers to start conversion by the A/D converter can be
skipped. skipped
- Interrupt sources: 43 sources. - Interrupt sources: 43 sources.
- Buffer operation: - Buffer operation:
- Automatic transfer of register data (transfer from the buffer - Automatic transfer of register data (transfer from the buffer
...@@ -68,9 +68,9 @@ description: | ...@@ -68,9 +68,9 @@ description: |
- A/D converter start triggers can be generated - A/D converter start triggers can be generated
- A/D converter start request delaying function enables A/D converter - A/D converter start request delaying function enables A/D converter
to be started with any desired timing and to be synchronized with to be started with any desired timing and to be synchronized with
PWM output. PWM output
- Low power consumption function - Low power consumption function
- The MTU3a can be placed in the module-stop state. - The MTU3a can be placed in the module-stop state
There are two phase counting modes. 16-bit phase counting mode in which There are two phase counting modes. 16-bit phase counting mode in which
MTU1 and MTU2 operate independently, and cascade connection 32-bit phase MTU1 and MTU2 operate independently, and cascade connection 32-bit phase
...@@ -109,6 +109,7 @@ properties: ...@@ -109,6 +109,7 @@ properties:
compatible: compatible:
items: items:
- enum: - enum:
- renesas,r9a07g043-mtu3 # RZ/{G2UL,Five}
- renesas,r9a07g044-mtu3 # RZ/G2{L,LC} - renesas,r9a07g044-mtu3 # RZ/G2{L,LC}
- renesas,r9a07g054-mtu3 # RZ/V2L - renesas,r9a07g054-mtu3 # RZ/V2L
- const: renesas,rz-mtu3 - const: renesas,rz-mtu3
...@@ -169,27 +170,27 @@ properties: ...@@ -169,27 +170,27 @@ properties:
- const: tgib0 - const: tgib0
- const: tgic0 - const: tgic0
- const: tgid0 - const: tgid0
- const: tgiv0 - const: tciv0
- const: tgie0 - const: tgie0
- const: tgif0 - const: tgif0
- const: tgia1 - const: tgia1
- const: tgib1 - const: tgib1
- const: tgiv1 - const: tciv1
- const: tgiu1 - const: tciu1
- const: tgia2 - const: tgia2
- const: tgib2 - const: tgib2
- const: tgiv2 - const: tciv2
- const: tgiu2 - const: tciu2
- const: tgia3 - const: tgia3
- const: tgib3 - const: tgib3
- const: tgic3 - const: tgic3
- const: tgid3 - const: tgid3
- const: tgiv3 - const: tciv3
- const: tgia4 - const: tgia4
- const: tgib4 - const: tgib4
- const: tgic4 - const: tgic4
- const: tgid4 - const: tgid4
- const: tgiv4 - const: tciv4
- const: tgiu5 - const: tgiu5
- const: tgiv5 - const: tgiv5
- const: tgiw5 - const: tgiw5
...@@ -197,18 +198,18 @@ properties: ...@@ -197,18 +198,18 @@ properties:
- const: tgib6 - const: tgib6
- const: tgic6 - const: tgic6
- const: tgid6 - const: tgid6
- const: tgiv6 - const: tciv6
- const: tgia7 - const: tgia7
- const: tgib7 - const: tgib7
- const: tgic7 - const: tgic7
- const: tgid7 - const: tgid7
- const: tgiv7 - const: tciv7
- const: tgia8 - const: tgia8
- const: tgib8 - const: tgib8
- const: tgic8 - const: tgic8
- const: tgid8 - const: tgid8
- const: tgiv8 - const: tciv8
- const: tgiu8 - const: tciu8
clocks: clocks:
maxItems: 1 maxItems: 1
...@@ -285,16 +286,16 @@ examples: ...@@ -285,16 +286,16 @@ examples:
<GIC_SPI 211 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 211 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tgiv0", "tgie0", interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tciv0", "tgie0",
"tgif0", "tgif0",
"tgia1", "tgib1", "tgiv1", "tgiu1", "tgia1", "tgib1", "tciv1", "tciu1",
"tgia2", "tgib2", "tgiv2", "tgiu2", "tgia2", "tgib2", "tciv2", "tciu2",
"tgia3", "tgib3", "tgic3", "tgid3", "tgiv3", "tgia3", "tgib3", "tgic3", "tgid3", "tciv3",
"tgia4", "tgib4", "tgic4", "tgid4", "tgiv4", "tgia4", "tgib4", "tgic4", "tgid4", "tciv4",
"tgiu5", "tgiv5", "tgiw5", "tgiu5", "tgiv5", "tgiw5",
"tgia6", "tgib6", "tgic6", "tgid6", "tgiv6", "tgia6", "tgib6", "tgic6", "tgid6", "tciv6",
"tgia7", "tgib7", "tgic7", "tgid7", "tgiv7", "tgia7", "tgib7", "tgic7", "tgid7", "tciv7",
"tgia8", "tgib8", "tgic8", "tgid8", "tgiv8", "tgiu8"; "tgia8", "tgib8", "tgic8", "tgid8", "tciv8", "tciu8";
clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
power-domains = <&cpg>; power-domains = <&cpg>;
resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
......
...@@ -732,4 +732,15 @@ config GOLDFISH_TIMER ...@@ -732,4 +732,15 @@ config GOLDFISH_TIMER
help help
Support for the timer/counter of goldfish-rtc Support for the timer/counter of goldfish-rtc
config EP93XX_TIMER
bool "Cirrus Logic ep93xx timer driver" if COMPILE_TEST
depends on ARCH_EP93XX
depends on GENERIC_CLOCKEVENTS
depends on HAS_IOMEM
select CLKSRC_MMIO
select TIMER_OF
help
Enables support for the Cirrus Logic timer block
EP93XX.
endmenu endmenu
...@@ -89,3 +89,4 @@ obj-$(CONFIG_MSC313E_TIMER) += timer-msc313e.o ...@@ -89,3 +89,4 @@ obj-$(CONFIG_MSC313E_TIMER) += timer-msc313e.o
obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o
obj-$(CONFIG_GXP_TIMER) += timer-gxp.o obj-$(CONFIG_GXP_TIMER) += timer-gxp.o
obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o
obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o
...@@ -315,6 +315,7 @@ static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx) ...@@ -315,6 +315,7 @@ static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx)
writel(mck_divisor_idx /* likely divide-by-8 */ writel(mck_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE | ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP /* free-run */ | ATMEL_TC_WAVESEL_UP /* free-run */
| ATMEL_TC_ASWTRG_SET /* TIOA0 rises at software trigger */
| ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */ | ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
| ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */ | ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
tcaddr + ATMEL_TC_REG(0, CMR)); tcaddr + ATMEL_TC_REG(0, CMR));
......
// SPDX-License-Identifier: GPL-2.0
/*
* Cirrus Logic EP93xx timer driver.
* Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me>
*
* Based on a rewrite of arch/arm/mach-ep93xx/timer.c:
*/
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/sched_clock.h>
#include <asm/mach/time.h>
/*************************************************************************
* Timer handling for EP93xx
*************************************************************************
* The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and
* 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
* an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz,
* is free-running, and can't generate interrupts.
*
* The 508 kHz timers are ideal for use for the timer interrupt, as the
* most common values of HZ divide 508 kHz nicely. We pick the 32 bit
* timer (timer 3) to get as long sleep intervals as possible when using
* CONFIG_NO_HZ.
*
* The higher clock rate of timer 4 makes it a better choice than the
* other timers for use as clock source and for sched_clock(), providing
* a stable 40 bit time base.
*************************************************************************
*/
#define EP93XX_TIMER1_LOAD 0x00
#define EP93XX_TIMER1_VALUE 0x04
#define EP93XX_TIMER1_CONTROL 0x08
#define EP93XX_TIMER123_CONTROL_ENABLE BIT(7)
#define EP93XX_TIMER123_CONTROL_MODE BIT(6)
#define EP93XX_TIMER123_CONTROL_CLKSEL BIT(3)
#define EP93XX_TIMER1_CLEAR 0x0c
#define EP93XX_TIMER2_LOAD 0x20
#define EP93XX_TIMER2_VALUE 0x24
#define EP93XX_TIMER2_CONTROL 0x28
#define EP93XX_TIMER2_CLEAR 0x2c
/*
* This read-only register contains the low word of the time stamp debug timer
* ( Timer4). When this register is read, the high byte of the Timer4 counter is
* saved in the Timer4ValueHigh register.
*/
#define EP93XX_TIMER4_VALUE_LOW 0x60
#define EP93XX_TIMER4_VALUE_HIGH 0x64
#define EP93XX_TIMER4_VALUE_HIGH_ENABLE BIT(8)
#define EP93XX_TIMER3_LOAD 0x80
#define EP93XX_TIMER3_VALUE 0x84
#define EP93XX_TIMER3_CONTROL 0x88
#define EP93XX_TIMER3_CLEAR 0x8c
#define EP93XX_TIMER123_RATE 508469
#define EP93XX_TIMER4_RATE 983040
struct ep93xx_tcu {
void __iomem *base;
};
static struct ep93xx_tcu *ep93xx_tcu;
static u64 ep93xx_clocksource_read(struct clocksource *c)
{
struct ep93xx_tcu *tcu = ep93xx_tcu;
return lo_hi_readq(tcu->base + EP93XX_TIMER4_VALUE_LOW) & GENMASK_ULL(39, 0);
}
static u64 notrace ep93xx_read_sched_clock(void)
{
return ep93xx_clocksource_read(NULL);
}
static int ep93xx_clkevt_set_next_event(unsigned long next,
struct clock_event_device *evt)
{
struct ep93xx_tcu *tcu = ep93xx_tcu;
/* Default mode: periodic, off, 508 kHz */
u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
EP93XX_TIMER123_CONTROL_CLKSEL;
/* Clear timer */
writel(tmode, tcu->base + EP93XX_TIMER3_CONTROL);
/* Set next event */
writel(next, tcu->base + EP93XX_TIMER3_LOAD);
writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
tcu->base + EP93XX_TIMER3_CONTROL);
return 0;
}
static int ep93xx_clkevt_shutdown(struct clock_event_device *evt)
{
struct ep93xx_tcu *tcu = ep93xx_tcu;
/* Disable timer */
writel(0, tcu->base + EP93XX_TIMER3_CONTROL);
return 0;
}
static struct clock_event_device ep93xx_clockevent = {
.name = "timer1",
.features = CLOCK_EVT_FEAT_ONESHOT,
.set_state_shutdown = ep93xx_clkevt_shutdown,
.set_state_oneshot = ep93xx_clkevt_shutdown,
.tick_resume = ep93xx_clkevt_shutdown,
.set_next_event = ep93xx_clkevt_set_next_event,
.rating = 300,
};
static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
{
struct ep93xx_tcu *tcu = ep93xx_tcu;
struct clock_event_device *evt = dev_id;
/* Writing any value clears the timer interrupt */
writel(1, tcu->base + EP93XX_TIMER3_CLEAR);
evt->event_handler(evt);
return IRQ_HANDLED;
}
static int __init ep93xx_timer_of_init(struct device_node *np)
{
int irq;
unsigned long flags = IRQF_TIMER | IRQF_IRQPOLL;
struct ep93xx_tcu *tcu;
int ret;
tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
if (!tcu)
return -ENOMEM;
tcu->base = of_iomap(np, 0);
if (!tcu->base) {
pr_err("Can't remap registers\n");
ret = -ENXIO;
goto out_free;
}
ep93xx_tcu = tcu;
irq = irq_of_parse_and_map(np, 0);
if (irq == 0)
irq = -EINVAL;
if (irq < 0) {
pr_err("EP93XX Timer Can't parse IRQ %d", irq);
goto out_free;
}
/* Enable and register clocksource and sched_clock on timer 4 */
writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
tcu->base + EP93XX_TIMER4_VALUE_HIGH);
clocksource_mmio_init(NULL, "timer4",
EP93XX_TIMER4_RATE, 200, 40,
ep93xx_clocksource_read);
sched_clock_register(ep93xx_read_sched_clock, 40,
EP93XX_TIMER4_RATE);
/* Set up clockevent on timer 3 */
if (request_irq(irq, ep93xx_timer_interrupt, flags, "ep93xx timer",
&ep93xx_clockevent))
pr_err("Failed to request irq %d (ep93xx timer)\n", irq);
clockevents_config_and_register(&ep93xx_clockevent,
EP93XX_TIMER123_RATE,
1,
UINT_MAX);
return 0;
out_free:
kfree(tcu);
return ret;
}
TIMER_OF_DECLARE(ep93xx_timer, "cirrus,ep9301-timer", ep93xx_timer_of_init);
...@@ -434,12 +434,16 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t ...@@ -434,12 +434,16 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
return -ENOMEM; return -ENOMEM;
imxtm->base = of_iomap(np, 0); imxtm->base = of_iomap(np, 0);
if (!imxtm->base) if (!imxtm->base) {
return -ENXIO; ret = -ENXIO;
goto err_kfree;
}
imxtm->irq = irq_of_parse_and_map(np, 0); imxtm->irq = irq_of_parse_and_map(np, 0);
if (imxtm->irq <= 0) if (imxtm->irq <= 0) {
return -EINVAL; ret = -EINVAL;
goto err_kfree;
}
imxtm->clk_ipg = of_clk_get_by_name(np, "ipg"); imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
...@@ -452,11 +456,15 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t ...@@ -452,11 +456,15 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
ret = _mxc_timer_init(imxtm); ret = _mxc_timer_init(imxtm);
if (ret) if (ret)
return ret; goto err_kfree;
initialized = 1; initialized = 1;
return 0; return 0;
err_kfree:
kfree(imxtm);
return ret;
} }
static int __init imx1_timer_init_dt(struct device_node *np) static int __init imx1_timer_init_dt(struct device_node *np)
......
...@@ -212,6 +212,10 @@ TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); ...@@ -212,6 +212,10 @@ TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static int __init riscv_timer_acpi_init(struct acpi_table_header *table) static int __init riscv_timer_acpi_init(struct acpi_table_header *table)
{ {
struct acpi_table_rhct *rhct = (struct acpi_table_rhct *)table;
riscv_timer_cannot_wake_cpu = rhct->flags & ACPI_RHCT_TIMER_CANNOT_WAKEUP_CPU;
return riscv_timer_init_common(); return riscv_timer_init_common();
} }
......
...@@ -256,10 +256,8 @@ static int sun5i_timer_probe(struct platform_device *pdev) ...@@ -256,10 +256,8 @@ static int sun5i_timer_probe(struct platform_device *pdev)
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
dev_err(dev, "Can't get IRQ\n");
return irq; return irq;
}
clk = devm_clk_get_enabled(dev, NULL); clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
......
...@@ -140,6 +140,8 @@ struct dmtimer { ...@@ -140,6 +140,8 @@ struct dmtimer {
struct platform_device *pdev; struct platform_device *pdev;
struct list_head node; struct list_head node;
struct notifier_block nb; struct notifier_block nb;
struct notifier_block fclk_nb;
unsigned long fclk_rate;
}; };
static u32 omap_reserved_systimers; static u32 omap_reserved_systimers;
...@@ -253,8 +255,7 @@ static inline void __omap_dm_timer_enable_posted(struct dmtimer *timer) ...@@ -253,8 +255,7 @@ static inline void __omap_dm_timer_enable_posted(struct dmtimer *timer)
timer->posted = OMAP_TIMER_POSTED; timer->posted = OMAP_TIMER_POSTED;
} }
static inline void __omap_dm_timer_stop(struct dmtimer *timer, static inline void __omap_dm_timer_stop(struct dmtimer *timer)
unsigned long rate)
{ {
u32 l; u32 l;
...@@ -269,7 +270,7 @@ static inline void __omap_dm_timer_stop(struct dmtimer *timer, ...@@ -269,7 +270,7 @@ static inline void __omap_dm_timer_stop(struct dmtimer *timer,
* Wait for functional clock period x 3.5 to make sure that * Wait for functional clock period x 3.5 to make sure that
* timer is stopped * timer is stopped
*/ */
udelay(3500000 / rate + 1); udelay(3500000 / timer->fclk_rate + 1);
#endif #endif
} }
...@@ -348,6 +349,21 @@ static int omap_timer_context_notifier(struct notifier_block *nb, ...@@ -348,6 +349,21 @@ static int omap_timer_context_notifier(struct notifier_block *nb,
return NOTIFY_OK; return NOTIFY_OK;
} }
static int omap_timer_fclk_notifier(struct notifier_block *nb,
unsigned long event, void *data)
{
struct clk_notifier_data *clk_data = data;
struct dmtimer *timer = container_of(nb, struct dmtimer, fclk_nb);
switch (event) {
case POST_RATE_CHANGE:
timer->fclk_rate = clk_data->new_rate;
return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}
static int omap_dm_timer_reset(struct dmtimer *timer) static int omap_dm_timer_reset(struct dmtimer *timer)
{ {
u32 l, timeout = 100000; u32 l, timeout = 100000;
...@@ -754,7 +770,6 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie) ...@@ -754,7 +770,6 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie)
{ {
struct dmtimer *timer; struct dmtimer *timer;
struct device *dev; struct device *dev;
unsigned long rate = 0;
timer = to_dmtimer(cookie); timer = to_dmtimer(cookie);
if (unlikely(!timer)) if (unlikely(!timer))
...@@ -762,10 +777,7 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie) ...@@ -762,10 +777,7 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie)
dev = &timer->pdev->dev; dev = &timer->pdev->dev;
if (!timer->omap1) __omap_dm_timer_stop(timer);
rate = clk_get_rate(timer->fclk);
__omap_dm_timer_stop(timer, rate);
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
...@@ -1124,6 +1136,14 @@ static int omap_dm_timer_probe(struct platform_device *pdev) ...@@ -1124,6 +1136,14 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
timer->fclk = devm_clk_get(dev, "fck"); timer->fclk = devm_clk_get(dev, "fck");
if (IS_ERR(timer->fclk)) if (IS_ERR(timer->fclk))
return PTR_ERR(timer->fclk); return PTR_ERR(timer->fclk);
timer->fclk_nb.notifier_call = omap_timer_fclk_notifier;
ret = devm_clk_notifier_register(dev, timer->fclk,
&timer->fclk_nb);
if (ret)
return ret;
timer->fclk_rate = clk_get_rate(timer->fclk);
} else { } else {
timer->fclk = ERR_PTR(-ENODEV); timer->fclk = ERR_PTR(-ENODEV);
} }
......
...@@ -225,6 +225,23 @@ static inline bool is_leap_year(unsigned int year) ...@@ -225,6 +225,23 @@ static inline bool is_leap_year(unsigned int year)
return (!(year % 4) && (year % 100)) || !(year % 400); return (!(year % 4) && (year % 100)) || !(year % 400);
} }
/**
* rtc_bound_alarmtime() - Return alarm time bound by rtc limit
* @rtc: Pointer to rtc device structure
* @requested: Requested alarm timeout
*
* Return: Alarm timeout bound by maximum alarm time supported by rtc.
*/
static inline ktime_t rtc_bound_alarmtime(struct rtc_device *rtc,
ktime_t requested)
{
if (rtc->alarm_offset_max &&
rtc->alarm_offset_max * MSEC_PER_SEC < ktime_to_ms(requested))
return ms_to_ktime(rtc->alarm_offset_max * MSEC_PER_SEC);
return requested;
}
#define devm_rtc_register_device(device) \ #define devm_rtc_register_device(device) \
__devm_rtc_register_device(THIS_MODULE, device) __devm_rtc_register_device(THIS_MODULE, device)
......
...@@ -140,14 +140,6 @@ extern unsigned long tick_nohz_get_idle_calls(void); ...@@ -140,14 +140,6 @@ extern unsigned long tick_nohz_get_idle_calls(void);
extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu); extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu);
extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time); extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
static inline void tick_nohz_idle_stop_tick_protected(void)
{
local_irq_disable();
tick_nohz_idle_stop_tick();
local_irq_enable();
}
#else /* !CONFIG_NO_HZ_COMMON */ #else /* !CONFIG_NO_HZ_COMMON */
#define tick_nohz_enabled (0) #define tick_nohz_enabled (0)
static inline int tick_nohz_tick_stopped(void) { return 0; } static inline int tick_nohz_tick_stopped(void) { return 0; }
...@@ -170,8 +162,6 @@ static inline ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next) ...@@ -170,8 +162,6 @@ static inline ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next)
} }
static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; } static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; } static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
static inline void tick_nohz_idle_stop_tick_protected(void) { }
#endif /* !CONFIG_NO_HZ_COMMON */ #endif /* !CONFIG_NO_HZ_COMMON */
#ifdef CONFIG_NO_HZ_FULL #ifdef CONFIG_NO_HZ_FULL
......
...@@ -290,6 +290,17 @@ static int alarmtimer_suspend(struct device *dev) ...@@ -290,6 +290,17 @@ static int alarmtimer_suspend(struct device *dev)
rtc_timer_cancel(rtc, &rtctimer); rtc_timer_cancel(rtc, &rtctimer);
rtc_read_time(rtc, &tm); rtc_read_time(rtc, &tm);
now = rtc_tm_to_ktime(tm); now = rtc_tm_to_ktime(tm);
/*
* If the RTC alarm timer only supports a limited time offset, set the
* alarm time to the maximum supported value.
* The system may wake up earlier (possibly much earlier) than expected
* when the alarmtimer runs. This is the best the kernel can do if
* the alarmtimer exceeds the time that the rtc device can be programmed
* for.
*/
min = rtc_bound_alarmtime(rtc, min);
now = ktime_add(now, min); now = ktime_add(now, min);
/* Set alarm, if in the past reject suspend briefly to handle */ /* Set alarm, if in the past reject suspend briefly to handle */
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment