Skip to content

Commit 0c617a3

Browse files
Niklas Söderlunddlezcano
authored andcommitted
clocksource/drivers/sh_cmt: Split start/stop of clock source and events
The CMT do a housekeeping such as dealing with runtime PM and enable/disable clocks when either a clock source is enabled, or when a new clock event is registered. Doing this type of housekeeping for when a clock event is registered is not always possible as it can happen in contexts where holding spinlocks is not possible. However doing it when registering a clock source is possible. As a first step to address this design break apart the CMT start and stop functions. The path for clock sources need not change, while the one for clock events need to be reworked in future work. There is no indented functional change, just breaking the two use-cases controlled by a flag into two distinct functions. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/r/20250910142657.1148696-2-niklas.soderlund+renesas@ragnatech.se
1 parent cd32e59 commit 0c617a3

1 file changed

Lines changed: 59 additions & 25 deletions

File tree

drivers/clocksource/sh_cmt.c

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -578,60 +578,94 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
578578
return IRQ_HANDLED;
579579
}
580580

581-
static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag)
581+
static int sh_cmt_start_clocksource(struct sh_cmt_channel *ch)
582582
{
583583
int ret = 0;
584584
unsigned long flags;
585585

586-
if (flag & FLAG_CLOCKSOURCE)
587-
pm_runtime_get_sync(&ch->cmt->pdev->dev);
586+
pm_runtime_get_sync(&ch->cmt->pdev->dev);
588587

589588
raw_spin_lock_irqsave(&ch->lock, flags);
590589

591-
if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {
592-
if (flag & FLAG_CLOCKEVENT)
593-
pm_runtime_get_sync(&ch->cmt->pdev->dev);
590+
if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
594591
ret = sh_cmt_enable(ch);
595-
}
596592

597593
if (ret)
598594
goto out;
599-
ch->flags |= flag;
595+
596+
ch->flags |= FLAG_CLOCKSOURCE;
600597

601598
/* setup timeout if no clockevent */
602-
if (ch->cmt->num_channels == 1 &&
603-
flag == FLAG_CLOCKSOURCE && (!(ch->flags & FLAG_CLOCKEVENT)))
599+
if (ch->cmt->num_channels == 1 && !(ch->flags & FLAG_CLOCKEVENT))
604600
__sh_cmt_set_next(ch, ch->max_match_value);
601+
out:
602+
raw_spin_unlock_irqrestore(&ch->lock, flags);
603+
604+
return ret;
605+
}
606+
607+
static void sh_cmt_stop_clocksource(struct sh_cmt_channel *ch)
608+
{
609+
unsigned long flags;
610+
unsigned long f;
611+
612+
raw_spin_lock_irqsave(&ch->lock, flags);
613+
614+
f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
615+
616+
ch->flags &= ~FLAG_CLOCKSOURCE;
617+
618+
if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
619+
sh_cmt_disable(ch);
620+
621+
raw_spin_unlock_irqrestore(&ch->lock, flags);
622+
623+
pm_runtime_put(&ch->cmt->pdev->dev);
624+
}
625+
626+
static int sh_cmt_start_clockevent(struct sh_cmt_channel *ch)
627+
{
628+
int ret = 0;
629+
unsigned long flags;
630+
631+
raw_spin_lock_irqsave(&ch->lock, flags);
632+
633+
if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {
634+
pm_runtime_get_sync(&ch->cmt->pdev->dev);
635+
ret = sh_cmt_enable(ch);
636+
}
637+
638+
if (ret)
639+
goto out;
640+
641+
ch->flags |= FLAG_CLOCKEVENT;
605642
out:
606643
raw_spin_unlock_irqrestore(&ch->lock, flags);
607644

608645
return ret;
609646
}
610647

611-
static void sh_cmt_stop(struct sh_cmt_channel *ch, unsigned long flag)
648+
static void sh_cmt_stop_clockevent(struct sh_cmt_channel *ch)
612649
{
613650
unsigned long flags;
614651
unsigned long f;
615652

616653
raw_spin_lock_irqsave(&ch->lock, flags);
617654

618655
f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
619-
ch->flags &= ~flag;
656+
657+
ch->flags &= ~FLAG_CLOCKEVENT;
620658

621659
if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {
622660
sh_cmt_disable(ch);
623-
if (flag & FLAG_CLOCKEVENT)
624-
pm_runtime_put(&ch->cmt->pdev->dev);
661+
pm_runtime_put(&ch->cmt->pdev->dev);
625662
}
626663

627664
/* adjust the timeout to maximum if only clocksource left */
628-
if ((flag == FLAG_CLOCKEVENT) && (ch->flags & FLAG_CLOCKSOURCE))
665+
if (ch->flags & FLAG_CLOCKSOURCE)
629666
__sh_cmt_set_next(ch, ch->max_match_value);
630667

631668
raw_spin_unlock_irqrestore(&ch->lock, flags);
632-
633-
if (flag & FLAG_CLOCKSOURCE)
634-
pm_runtime_put(&ch->cmt->pdev->dev);
635669
}
636670

637671
static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
@@ -672,7 +706,7 @@ static int sh_cmt_clocksource_enable(struct clocksource *cs)
672706

673707
ch->total_cycles = 0;
674708

675-
ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE);
709+
ret = sh_cmt_start_clocksource(ch);
676710
if (!ret)
677711
ch->cs_enabled = true;
678712

@@ -685,7 +719,7 @@ static void sh_cmt_clocksource_disable(struct clocksource *cs)
685719

686720
WARN_ON(!ch->cs_enabled);
687721

688-
sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
722+
sh_cmt_stop_clocksource(ch);
689723
ch->cs_enabled = false;
690724
}
691725

@@ -696,7 +730,7 @@ static void sh_cmt_clocksource_suspend(struct clocksource *cs)
696730
if (!ch->cs_enabled)
697731
return;
698732

699-
sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
733+
sh_cmt_stop_clocksource(ch);
700734
dev_pm_genpd_suspend(&ch->cmt->pdev->dev);
701735
}
702736

@@ -708,7 +742,7 @@ static void sh_cmt_clocksource_resume(struct clocksource *cs)
708742
return;
709743

710744
dev_pm_genpd_resume(&ch->cmt->pdev->dev);
711-
sh_cmt_start(ch, FLAG_CLOCKSOURCE);
745+
sh_cmt_start_clocksource(ch);
712746
}
713747

714748
static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
@@ -740,7 +774,7 @@ static struct sh_cmt_channel *ced_to_sh_cmt(struct clock_event_device *ced)
740774

741775
static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic)
742776
{
743-
sh_cmt_start(ch, FLAG_CLOCKEVENT);
777+
sh_cmt_start_clockevent(ch);
744778

745779
if (periodic)
746780
sh_cmt_set_next(ch, ((ch->cmt->rate + HZ/2) / HZ) - 1);
@@ -752,7 +786,7 @@ static int sh_cmt_clock_event_shutdown(struct clock_event_device *ced)
752786
{
753787
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
754788

755-
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
789+
sh_cmt_stop_clockevent(ch);
756790
return 0;
757791
}
758792

@@ -763,7 +797,7 @@ static int sh_cmt_clock_event_set_state(struct clock_event_device *ced,
763797

764798
/* deal with old setting first */
765799
if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
766-
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
800+
sh_cmt_stop_clockevent(ch);
767801

768802
dev_info(&ch->cmt->pdev->dev, "ch%u: used for %s clock events\n",
769803
ch->index, periodic ? "periodic" : "oneshot");

0 commit comments

Comments
 (0)