2024-02-05 03:13:56

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v4 0/3] clocksource: imx-sysctr: support i.MX95

i.MX95 System Counter module control register space is blocked
by SCMI firmware, so we use Read Register space to get the counter.

V2:
- imx95 is not compatible with the existing hardware, so add a
seperate entry for i.MX95 in dt-binding.
- Per Marco's comments, the global variables was removed except
to_sysctr. And add a new TIMER_OF_DECLARE entry for i.MX95

Signed-off-by: Peng Fan <[email protected]>
---
Changes in v4:
- Add A-b in patch 1
- Include slab.h in patch 2 to fix kernel build failure for i386 compile
test.
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- Drop items in patch 1 per Conor's comments
- Link to v2: https://lore.kernel.org/r/[email protected]

---
Peng Fan (3):
dt-bindings: timer: nxp,sysctr-timer: support i.MX95
clocksource/drivers/imx-sysctr: drop use global variables
clocksource/drivers/imx-sysctr: support i.MX95

.../bindings/timer/nxp,sysctr-timer.yaml | 4 +-
drivers/clocksource/timer-imx-sysctr.c | 117 +++++++++++++++------
2 files changed, 90 insertions(+), 31 deletions(-)
---
base-commit: 01af33cc9894b4489fb68fa35c40e9fe85df63dc
change-id: 20240125-imx-sysctr-3a89a0852376

Best regards,
--
Peng Fan <[email protected]>



2024-02-05 03:14:12

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v4 1/3] dt-bindings: timer: nxp,sysctr-timer: support i.MX95

From: Peng Fan <[email protected]>

Add i.MX95 System counter module compatible string, the SCMI
firmware blocks access to control register, so should not
add "nxp,sysctr-timer" as fallback.

Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Peng Fan <[email protected]>
---
Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml b/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
index 2b9653dafab8..891cca009528 100644
--- a/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
@@ -18,7 +18,9 @@ description: |

properties:
compatible:
- const: nxp,sysctr-timer
+ enum:
+ - nxp,imx95-sysctr-timer
+ - nxp,sysctr-timer

reg:
maxItems: 1

--
2.37.1


2024-02-05 03:14:29

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v4 2/3] clocksource/drivers/imx-sysctr: drop use global variables

From: Peng Fan <[email protected]>

Clean up code to not use global variables and introduce sysctr_private
structure to prepare the support for i.MX95.

Signed-off-by: Peng Fan <[email protected]>
---
drivers/clocksource/timer-imx-sysctr.c | 76 ++++++++++++++++++++--------------
1 file changed, 44 insertions(+), 32 deletions(-)

diff --git a/drivers/clocksource/timer-imx-sysctr.c b/drivers/clocksource/timer-imx-sysctr.c
index 5a7a951c4efc..c075ea89a214 100644
--- a/drivers/clocksource/timer-imx-sysctr.c
+++ b/drivers/clocksource/timer-imx-sysctr.c
@@ -4,6 +4,7 @@

#include <linux/interrupt.h>
#include <linux/clockchips.h>
+#include <linux/slab.h>

#include "timer-of.h"

@@ -20,32 +21,39 @@

#define SYS_CTR_CLK_DIV 0x3

-static void __iomem *sys_ctr_base __ro_after_init;
-static u32 cmpcr __ro_after_init;
+struct sysctr_private {
+ u32 cmpcr;
+};

-static void sysctr_timer_enable(bool enable)
+static void sysctr_timer_enable(struct clock_event_device *evt, bool enable)
{
- writel(enable ? cmpcr | SYS_CTR_EN : cmpcr, sys_ctr_base + CMPCR);
+ struct timer_of *to = to_timer_of(evt);
+ struct sysctr_private *priv = to->private_data;
+ void __iomem *base = timer_of_base(to);
+
+ writel(enable ? priv->cmpcr | SYS_CTR_EN : priv->cmpcr, base + CMPCR);
}

-static void sysctr_irq_acknowledge(void)
+static void sysctr_irq_acknowledge(struct clock_event_device *evt)
{
/*
* clear the enable bit(EN =0) will clear
* the status bit(ISTAT = 0), then the interrupt
* signal will be negated(acknowledged).
*/
- sysctr_timer_enable(false);
+ sysctr_timer_enable(evt, false);
}

-static inline u64 sysctr_read_counter(void)
+static inline u64 sysctr_read_counter(struct clock_event_device *evt)
{
+ struct timer_of *to = to_timer_of(evt);
+ void __iomem *base = timer_of_base(to);
u32 cnt_hi, tmp_hi, cnt_lo;

do {
- cnt_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
- cnt_lo = readl_relaxed(sys_ctr_base + CNTCV_LO);
- tmp_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
+ cnt_hi = readl_relaxed(base + CNTCV_HI);
+ cnt_lo = readl_relaxed(base + CNTCV_LO);
+ tmp_hi = readl_relaxed(base + CNTCV_HI);
} while (tmp_hi != cnt_hi);

return ((u64) cnt_hi << 32) | cnt_lo;
@@ -54,22 +62,24 @@ static inline u64 sysctr_read_counter(void)
static int sysctr_set_next_event(unsigned long delta,
struct clock_event_device *evt)
{
+ struct timer_of *to = to_timer_of(evt);
+ void __iomem *base = timer_of_base(to);
u32 cmp_hi, cmp_lo;
u64 next;

- sysctr_timer_enable(false);
+ sysctr_timer_enable(evt, false);

- next = sysctr_read_counter();
+ next = sysctr_read_counter(evt);

next += delta;

cmp_hi = (next >> 32) & 0x00fffff;
cmp_lo = next & 0xffffffff;

- writel_relaxed(cmp_hi, sys_ctr_base + CMPCV_HI);
- writel_relaxed(cmp_lo, sys_ctr_base + CMPCV_LO);
+ writel_relaxed(cmp_hi, base + CMPCV_HI);
+ writel_relaxed(cmp_lo, base + CMPCV_LO);

- sysctr_timer_enable(true);
+ sysctr_timer_enable(evt, true);

return 0;
}
@@ -81,7 +91,7 @@ static int sysctr_set_state_oneshot(struct clock_event_device *evt)

static int sysctr_set_state_shutdown(struct clock_event_device *evt)
{
- sysctr_timer_enable(false);
+ sysctr_timer_enable(evt, false);

return 0;
}
@@ -90,7 +100,7 @@ static irqreturn_t sysctr_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;

- sysctr_irq_acknowledge();
+ sysctr_irq_acknowledge(evt);

evt->event_handler(evt);

@@ -117,34 +127,36 @@ static struct timer_of to_sysctr = {
},
};

-static void __init sysctr_clockevent_init(void)
-{
- to_sysctr.clkevt.cpumask = cpu_possible_mask;
-
- clockevents_config_and_register(&to_sysctr.clkevt,
- timer_of_rate(&to_sysctr),
- 0xff, 0x7fffffff);
-}
-
static int __init sysctr_timer_init(struct device_node *np)
{
- int ret = 0;
+ struct sysctr_private *priv;
+ void __iomem *base;
+ int ret;
+
+ priv = kzalloc(sizeof(struct sysctr_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;

ret = timer_of_init(np, &to_sysctr);
- if (ret)
+ if (ret) {
+ kfree(priv);
return ret;
+ }

if (!of_property_read_bool(np, "nxp,no-divider")) {
/* system counter clock is divided by 3 internally */
to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV;
}

- sys_ctr_base = timer_of_base(&to_sysctr);
- cmpcr = readl(sys_ctr_base + CMPCR);
- cmpcr &= ~SYS_CTR_EN;
+ to_sysctr.clkevt.cpumask = cpu_possible_mask;
+ to_sysctr.private_data = priv;

- sysctr_clockevent_init();
+ base = timer_of_base(&to_sysctr);
+ priv->cmpcr = readl(base + CMPCR) & ~SYS_CTR_EN;

+ clockevents_config_and_register(&to_sysctr.clkevt,
+ timer_of_rate(&to_sysctr),
+ 0xff, 0x7fffffff);
return 0;
}
TIMER_OF_DECLARE(sysctr_timer, "nxp,sysctr-timer", sysctr_timer_init);

--
2.37.1


2024-02-05 03:14:45

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v4 3/3] clocksource/drivers/imx-sysctr: support i.MX95

From: Peng Fan <[email protected]>

To i.MX95 System counter module, we use Read register space to get
the counter, not the Control register space to get the counter, because
System Manager firmware not allow Linux to read Control register space,
so add a new TIMER_OF_DECLARE entry for i.MX95.

Signed-off-by: Peng Fan <[email protected]>
---
drivers/clocksource/timer-imx-sysctr.c | 53 +++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/timer-imx-sysctr.c b/drivers/clocksource/timer-imx-sysctr.c
index c075ea89a214..44525813be1e 100644
--- a/drivers/clocksource/timer-imx-sysctr.c
+++ b/drivers/clocksource/timer-imx-sysctr.c
@@ -9,12 +9,15 @@
#include "timer-of.h"

#define CMP_OFFSET 0x10000
+#define RD_OFFSET 0x20000

#define CNTCV_LO 0x8
#define CNTCV_HI 0xc
#define CMPCV_LO (CMP_OFFSET + 0x20)
#define CMPCV_HI (CMP_OFFSET + 0x24)
#define CMPCR (CMP_OFFSET + 0x2c)
+#define CNTCV_LO_IMX95 (RD_OFFSET + 0x8)
+#define CNTCV_HI_IMX95 (RD_OFFSET + 0xc)

#define SYS_CTR_EN 0x1
#define SYS_CTR_IRQ_MASK 0x2
@@ -23,6 +26,8 @@

struct sysctr_private {
u32 cmpcr;
+ u32 lo_off;
+ u32 hi_off;
};

static void sysctr_timer_enable(struct clock_event_device *evt, bool enable)
@@ -47,13 +52,14 @@ static void sysctr_irq_acknowledge(struct clock_event_device *evt)
static inline u64 sysctr_read_counter(struct clock_event_device *evt)
{
struct timer_of *to = to_timer_of(evt);
+ struct sysctr_private *priv = to->private_data;
void __iomem *base = timer_of_base(to);
u32 cnt_hi, tmp_hi, cnt_lo;

do {
- cnt_hi = readl_relaxed(base + CNTCV_HI);
- cnt_lo = readl_relaxed(base + CNTCV_LO);
- tmp_hi = readl_relaxed(base + CNTCV_HI);
+ cnt_hi = readl_relaxed(base + priv->hi_off);
+ cnt_lo = readl_relaxed(base + priv->lo_off);
+ tmp_hi = readl_relaxed(base + priv->hi_off);
} while (tmp_hi != cnt_hi);

return ((u64) cnt_hi << 32) | cnt_lo;
@@ -127,7 +133,7 @@ static struct timer_of to_sysctr = {
},
};

-static int __init sysctr_timer_init(struct device_node *np)
+static int __init __sysctr_timer_init(struct device_node *np)
{
struct sysctr_private *priv;
void __iomem *base;
@@ -154,9 +160,48 @@ static int __init sysctr_timer_init(struct device_node *np)
base = timer_of_base(&to_sysctr);
priv->cmpcr = readl(base + CMPCR) & ~SYS_CTR_EN;

+ return 0;
+}
+
+static int __init sysctr_timer_init(struct device_node *np)
+{
+ struct sysctr_private *priv;
+ int ret;
+
+ ret = __sysctr_timer_init(np);
+ if (ret)
+ return ret;
+
+ priv = to_sysctr.private_data;
+ priv->lo_off = CNTCV_LO;
+ priv->hi_off = CNTCV_HI;
+
clockevents_config_and_register(&to_sysctr.clkevt,
timer_of_rate(&to_sysctr),
0xff, 0x7fffffff);
+
return 0;
}
+
+static int __init sysctr_timer_imx95_init(struct device_node *np)
+{
+ struct sysctr_private *priv;
+ int ret;
+
+ ret = __sysctr_timer_init(np);
+ if (ret)
+ return ret;
+
+ priv = to_sysctr.private_data;
+ priv->lo_off = CNTCV_LO_IMX95;
+ priv->hi_off = CNTCV_HI_IMX95;
+
+ clockevents_config_and_register(&to_sysctr.clkevt,
+ timer_of_rate(&to_sysctr),
+ 0xff, 0x7fffffff);
+
+ return 0;
+}
+
TIMER_OF_DECLARE(sysctr_timer, "nxp,sysctr-timer", sysctr_timer_init);
+TIMER_OF_DECLARE(sysctr_timer_imx95, "nxp,imx95-sysctr-timer", sysctr_timer_imx95_init);

--
2.37.1


2024-02-18 01:37:40

by Peng Fan

[permalink] [raw]
Subject: RE: [PATCH v4 0/3] clocksource: imx-sysctr: support i.MX95

Hi Daniel,

> Subject: [PATCH v4 0/3] clocksource: imx-sysctr: support i.MX95
>
> i.MX95 System Counter module control register space is blocked by SCMI
> firmware, so we use Read Register space to get the counter.

Ping..

Thanks,
Peng.
>
> V2:
> - imx95 is not compatible with the existing hardware, so add a
> seperate entry for i.MX95 in dt-binding.
> - Per Marco's comments, the global variables was removed except
> to_sysctr. And add a new TIMER_OF_DECLARE entry for i.MX95
>
> Signed-off-by: Peng Fan <[email protected]>
> ---
> Changes in v4:
> - Add A-b in patch 1
> - Include slab.h in patch 2 to fix kernel build failure for i386 compile test.
> - Link to v3: https://lore.kernel.org/r/20240126-imx-sysctr-v3-0-
> [email protected]
>
> Changes in v3:
> - Drop items in patch 1 per Conor's comments
> - Link to v2: https://lore.kernel.org/r/20240125-imx-sysctr-v2-0-
> [email protected]
>
> ---
> Peng Fan (3):
> dt-bindings: timer: nxp,sysctr-timer: support i.MX95
> clocksource/drivers/imx-sysctr: drop use global variables
> clocksource/drivers/imx-sysctr: support i.MX95
>
> .../bindings/timer/nxp,sysctr-timer.yaml | 4 +-
> drivers/clocksource/timer-imx-sysctr.c | 117 +++++++++++++++------
> 2 files changed, 90 insertions(+), 31 deletions(-)
> ---
> base-commit: 01af33cc9894b4489fb68fa35c40e9fe85df63dc
> change-id: 20240125-imx-sysctr-3a89a0852376
>
> Best regards,
> --
> Peng Fan <[email protected]>

2024-02-18 10:35:10

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] clocksource: imx-sysctr: support i.MX95

On 05/02/2024 04:17, Peng Fan (OSS) wrote:
> i.MX95 System Counter module control register space is blocked
> by SCMI firmware, so we use Read Register space to get the counter.
>
> V2:
> - imx95 is not compatible with the existing hardware, so add a
> seperate entry for i.MX95 in dt-binding.
> - Per Marco's comments, the global variables was removed except
> to_sysctr. And add a new TIMER_OF_DECLARE entry for i.MX95
>
> Signed-off-by: Peng Fan <[email protected]>
> ---

Applied, thanks

--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


2024-03-18 10:09:30

by tip-bot2 for Tony Luck

[permalink] [raw]
Subject: [tip: timers/core] clocksource/drivers/imx-sysctr: Add i.MX95 support

The following commit has been merged into the timers/core branch of tip:

Commit-ID: b67686e971b06eee1be363b89863bd1217f65190
Gitweb: https://git.kernel.org/tip/b67686e971b06eee1be363b89863bd1217f65190
Author: Peng Fan <[email protected]>
AuthorDate: Mon, 05 Feb 2024 11:17:59 +08:00
Committer: Daniel Lezcano <[email protected]>
CommitterDate: Sun, 18 Feb 2024 10:45:36 +01:00

clocksource/drivers/imx-sysctr: Add i.MX95 support

To i.MX95 System counter module, we use Read register space to get
the counter, not the Control register space to get the counter, because
System Manager firmware not allow Linux to read Control register space,
so add a new TIMER_OF_DECLARE entry for i.MX95.

Signed-off-by: Peng Fan <[email protected]>
Signed-off-by: Daniel Lezcano <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
---
drivers/clocksource/timer-imx-sysctr.c | 53 +++++++++++++++++++++++--
1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/timer-imx-sysctr.c b/drivers/clocksource/timer-imx-sysctr.c
index c075ea8..4452581 100644
--- a/drivers/clocksource/timer-imx-sysctr.c
+++ b/drivers/clocksource/timer-imx-sysctr.c
@@ -9,12 +9,15 @@
#include "timer-of.h"

#define CMP_OFFSET 0x10000
+#define RD_OFFSET 0x20000

#define CNTCV_LO 0x8
#define CNTCV_HI 0xc
#define CMPCV_LO (CMP_OFFSET + 0x20)
#define CMPCV_HI (CMP_OFFSET + 0x24)
#define CMPCR (CMP_OFFSET + 0x2c)
+#define CNTCV_LO_IMX95 (RD_OFFSET + 0x8)
+#define CNTCV_HI_IMX95 (RD_OFFSET + 0xc)

#define SYS_CTR_EN 0x1
#define SYS_CTR_IRQ_MASK 0x2
@@ -23,6 +26,8 @@

struct sysctr_private {
u32 cmpcr;
+ u32 lo_off;
+ u32 hi_off;
};

static void sysctr_timer_enable(struct clock_event_device *evt, bool enable)
@@ -47,13 +52,14 @@ static void sysctr_irq_acknowledge(struct clock_event_device *evt)
static inline u64 sysctr_read_counter(struct clock_event_device *evt)
{
struct timer_of *to = to_timer_of(evt);
+ struct sysctr_private *priv = to->private_data;
void __iomem *base = timer_of_base(to);
u32 cnt_hi, tmp_hi, cnt_lo;

do {
- cnt_hi = readl_relaxed(base + CNTCV_HI);
- cnt_lo = readl_relaxed(base + CNTCV_LO);
- tmp_hi = readl_relaxed(base + CNTCV_HI);
+ cnt_hi = readl_relaxed(base + priv->hi_off);
+ cnt_lo = readl_relaxed(base + priv->lo_off);
+ tmp_hi = readl_relaxed(base + priv->hi_off);
} while (tmp_hi != cnt_hi);

return ((u64) cnt_hi << 32) | cnt_lo;
@@ -127,7 +133,7 @@ static struct timer_of to_sysctr = {
},
};

-static int __init sysctr_timer_init(struct device_node *np)
+static int __init __sysctr_timer_init(struct device_node *np)
{
struct sysctr_private *priv;
void __iomem *base;
@@ -154,9 +160,48 @@ static int __init sysctr_timer_init(struct device_node *np)
base = timer_of_base(&to_sysctr);
priv->cmpcr = readl(base + CMPCR) & ~SYS_CTR_EN;

+ return 0;
+}
+
+static int __init sysctr_timer_init(struct device_node *np)
+{
+ struct sysctr_private *priv;
+ int ret;
+
+ ret = __sysctr_timer_init(np);
+ if (ret)
+ return ret;
+
+ priv = to_sysctr.private_data;
+ priv->lo_off = CNTCV_LO;
+ priv->hi_off = CNTCV_HI;
+
clockevents_config_and_register(&to_sysctr.clkevt,
timer_of_rate(&to_sysctr),
0xff, 0x7fffffff);
+
return 0;
}
+
+static int __init sysctr_timer_imx95_init(struct device_node *np)
+{
+ struct sysctr_private *priv;
+ int ret;
+
+ ret = __sysctr_timer_init(np);
+ if (ret)
+ return ret;
+
+ priv = to_sysctr.private_data;
+ priv->lo_off = CNTCV_LO_IMX95;
+ priv->hi_off = CNTCV_HI_IMX95;
+
+ clockevents_config_and_register(&to_sysctr.clkevt,
+ timer_of_rate(&to_sysctr),
+ 0xff, 0x7fffffff);
+
+ return 0;
+}
+
TIMER_OF_DECLARE(sysctr_timer, "nxp,sysctr-timer", sysctr_timer_init);
+TIMER_OF_DECLARE(sysctr_timer_imx95, "nxp,imx95-sysctr-timer", sysctr_timer_imx95_init);

2024-03-18 10:09:44

by tip-bot2 for Tony Luck

[permalink] [raw]
Subject: [tip: timers/core] clocksource/drivers/imx-sysctr: Drop use global variables

The following commit has been merged into the timers/core branch of tip:

Commit-ID: 418062b548b138a1e6a9fde3a8ddf7fa77c44c9e
Gitweb: https://git.kernel.org/tip/418062b548b138a1e6a9fde3a8ddf7fa77c44c9e
Author: Peng Fan <[email protected]>
AuthorDate: Mon, 05 Feb 2024 11:17:58 +08:00
Committer: Daniel Lezcano <[email protected]>
CommitterDate: Sun, 18 Feb 2024 10:45:30 +01:00

clocksource/drivers/imx-sysctr: Drop use global variables

Clean up code to not use global variables and introduce sysctr_private
structure to prepare the support for i.MX95.

Signed-off-by: Peng Fan <[email protected]>
Signed-off-by: Daniel Lezcano <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
---
drivers/clocksource/timer-imx-sysctr.c | 76 ++++++++++++++-----------
1 file changed, 44 insertions(+), 32 deletions(-)

diff --git a/drivers/clocksource/timer-imx-sysctr.c b/drivers/clocksource/timer-imx-sysctr.c
index 5a7a951..c075ea8 100644
--- a/drivers/clocksource/timer-imx-sysctr.c
+++ b/drivers/clocksource/timer-imx-sysctr.c
@@ -4,6 +4,7 @@

#include <linux/interrupt.h>
#include <linux/clockchips.h>
+#include <linux/slab.h>

#include "timer-of.h"

@@ -20,32 +21,39 @@

#define SYS_CTR_CLK_DIV 0x3

-static void __iomem *sys_ctr_base __ro_after_init;
-static u32 cmpcr __ro_after_init;
+struct sysctr_private {
+ u32 cmpcr;
+};

-static void sysctr_timer_enable(bool enable)
+static void sysctr_timer_enable(struct clock_event_device *evt, bool enable)
{
- writel(enable ? cmpcr | SYS_CTR_EN : cmpcr, sys_ctr_base + CMPCR);
+ struct timer_of *to = to_timer_of(evt);
+ struct sysctr_private *priv = to->private_data;
+ void __iomem *base = timer_of_base(to);
+
+ writel(enable ? priv->cmpcr | SYS_CTR_EN : priv->cmpcr, base + CMPCR);
}

-static void sysctr_irq_acknowledge(void)
+static void sysctr_irq_acknowledge(struct clock_event_device *evt)
{
/*
* clear the enable bit(EN =0) will clear
* the status bit(ISTAT = 0), then the interrupt
* signal will be negated(acknowledged).
*/
- sysctr_timer_enable(false);
+ sysctr_timer_enable(evt, false);
}

-static inline u64 sysctr_read_counter(void)
+static inline u64 sysctr_read_counter(struct clock_event_device *evt)
{
+ struct timer_of *to = to_timer_of(evt);
+ void __iomem *base = timer_of_base(to);
u32 cnt_hi, tmp_hi, cnt_lo;

do {
- cnt_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
- cnt_lo = readl_relaxed(sys_ctr_base + CNTCV_LO);
- tmp_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
+ cnt_hi = readl_relaxed(base + CNTCV_HI);
+ cnt_lo = readl_relaxed(base + CNTCV_LO);
+ tmp_hi = readl_relaxed(base + CNTCV_HI);
} while (tmp_hi != cnt_hi);

return ((u64) cnt_hi << 32) | cnt_lo;
@@ -54,22 +62,24 @@ static inline u64 sysctr_read_counter(void)
static int sysctr_set_next_event(unsigned long delta,
struct clock_event_device *evt)
{
+ struct timer_of *to = to_timer_of(evt);
+ void __iomem *base = timer_of_base(to);
u32 cmp_hi, cmp_lo;
u64 next;

- sysctr_timer_enable(false);
+ sysctr_timer_enable(evt, false);

- next = sysctr_read_counter();
+ next = sysctr_read_counter(evt);

next += delta;

cmp_hi = (next >> 32) & 0x00fffff;
cmp_lo = next & 0xffffffff;

- writel_relaxed(cmp_hi, sys_ctr_base + CMPCV_HI);
- writel_relaxed(cmp_lo, sys_ctr_base + CMPCV_LO);
+ writel_relaxed(cmp_hi, base + CMPCV_HI);
+ writel_relaxed(cmp_lo, base + CMPCV_LO);

- sysctr_timer_enable(true);
+ sysctr_timer_enable(evt, true);

return 0;
}
@@ -81,7 +91,7 @@ static int sysctr_set_state_oneshot(struct clock_event_device *evt)

static int sysctr_set_state_shutdown(struct clock_event_device *evt)
{
- sysctr_timer_enable(false);
+ sysctr_timer_enable(evt, false);

return 0;
}
@@ -90,7 +100,7 @@ static irqreturn_t sysctr_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;

- sysctr_irq_acknowledge();
+ sysctr_irq_acknowledge(evt);

evt->event_handler(evt);

@@ -117,34 +127,36 @@ static struct timer_of to_sysctr = {
},
};

-static void __init sysctr_clockevent_init(void)
-{
- to_sysctr.clkevt.cpumask = cpu_possible_mask;
-
- clockevents_config_and_register(&to_sysctr.clkevt,
- timer_of_rate(&to_sysctr),
- 0xff, 0x7fffffff);
-}
-
static int __init sysctr_timer_init(struct device_node *np)
{
- int ret = 0;
+ struct sysctr_private *priv;
+ void __iomem *base;
+ int ret;
+
+ priv = kzalloc(sizeof(struct sysctr_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;

ret = timer_of_init(np, &to_sysctr);
- if (ret)
+ if (ret) {
+ kfree(priv);
return ret;
+ }

if (!of_property_read_bool(np, "nxp,no-divider")) {
/* system counter clock is divided by 3 internally */
to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV;
}

- sys_ctr_base = timer_of_base(&to_sysctr);
- cmpcr = readl(sys_ctr_base + CMPCR);
- cmpcr &= ~SYS_CTR_EN;
+ to_sysctr.clkevt.cpumask = cpu_possible_mask;
+ to_sysctr.private_data = priv;

- sysctr_clockevent_init();
+ base = timer_of_base(&to_sysctr);
+ priv->cmpcr = readl(base + CMPCR) & ~SYS_CTR_EN;

+ clockevents_config_and_register(&to_sysctr.clkevt,
+ timer_of_rate(&to_sysctr),
+ 0xff, 0x7fffffff);
return 0;
}
TIMER_OF_DECLARE(sysctr_timer, "nxp,sysctr-timer", sysctr_timer_init);

2024-03-18 10:09:50

by tip-bot2 for Tony Luck

[permalink] [raw]
Subject: [tip: timers/core] dt-bindings: timer: nxp,sysctr-timer: support i.MX95

The following commit has been merged into the timers/core branch of tip:

Commit-ID: 8ec11bd89e15f7858359f2c4c9eed1d7de739c3c
Gitweb: https://git.kernel.org/tip/8ec11bd89e15f7858359f2c4c9eed1d7de739c3c
Author: Peng Fan <[email protected]>
AuthorDate: Mon, 05 Feb 2024 11:17:57 +08:00
Committer: Daniel Lezcano <[email protected]>
CommitterDate: Sun, 18 Feb 2024 10:45:05 +01:00

dt-bindings: timer: nxp,sysctr-timer: support i.MX95

Add i.MX95 System counter module compatible string, the SCMI
firmware blocks access to control register, so should not
add "nxp,sysctr-timer" as fallback.

Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Peng Fan <[email protected]>
Signed-off-by: Daniel Lezcano <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
---
Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml b/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
index 2b9653d..891cca0 100644
--- a/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
@@ -18,7 +18,9 @@ description: |

properties:
compatible:
- const: nxp,sysctr-timer
+ enum:
+ - nxp,imx95-sysctr-timer
+ - nxp,sysctr-timer

reg:
maxItems: 1