|
|
@@ -0,0 +1,384 @@
|
|
|
+From 57cbfd333c9d65bfab1a06b49c75536ee28dc2ce Mon Sep 17 00:00:00 2001
|
|
|
+From: Sergio Paracuellos <[email protected]>
|
|
|
+Date: Mon, 28 Oct 2024 21:36:43 +0100
|
|
|
+Subject: clocksource/drivers/ralink: Add Ralink System Tick Counter driver
|
|
|
+
|
|
|
+System Tick Counter is present on Ralink SoCs RT3352 and MT7620. This
|
|
|
+driver has been in 'arch/mips/ralink' directory since the beggining of
|
|
|
+Ralink architecture support. However, it can be moved into a more proper
|
|
|
+place in 'drivers/clocksource'. Hence add it here adding also support for
|
|
|
+compile test targets and reducing LOC in architecture code folder.
|
|
|
+
|
|
|
+Signed-off-by: Sergio Paracuellos <[email protected]>
|
|
|
+Link: https://lore.kernel.org/r/[email protected]
|
|
|
+Signed-off-by: Daniel Lezcano <[email protected]>
|
|
|
+---
|
|
|
+ arch/mips/ralink/Kconfig | 7 --
|
|
|
+ arch/mips/ralink/Makefile | 2 -
|
|
|
+ arch/mips/ralink/cevt-rt3352.c | 153 -------------------------------------
|
|
|
+ drivers/clocksource/Kconfig | 9 +++
|
|
|
+ drivers/clocksource/Makefile | 1 +
|
|
|
+ drivers/clocksource/timer-ralink.c | 150 ++++++++++++++++++++++++++++++++++++
|
|
|
+ 6 files changed, 160 insertions(+), 162 deletions(-)
|
|
|
+ delete mode 100644 arch/mips/ralink/cevt-rt3352.c
|
|
|
+ create mode 100644 drivers/clocksource/timer-ralink.c
|
|
|
+
|
|
|
+--- a/arch/mips/ralink/Kconfig
|
|
|
++++ b/arch/mips/ralink/Kconfig
|
|
|
+@@ -1,13 +1,6 @@
|
|
|
+ # SPDX-License-Identifier: GPL-2.0
|
|
|
+ if RALINK
|
|
|
+
|
|
|
+-config CLKEVT_RT3352
|
|
|
+- bool
|
|
|
+- depends on SOC_RT305X || SOC_MT7620
|
|
|
+- default y
|
|
|
+- select TIMER_OF
|
|
|
+- select CLKSRC_MMIO
|
|
|
+-
|
|
|
+ config RALINK_ILL_ACC
|
|
|
+ bool
|
|
|
+ depends on SOC_RT305X
|
|
|
+--- a/arch/mips/ralink/Makefile
|
|
|
++++ b/arch/mips/ralink/Makefile
|
|
|
+@@ -10,8 +10,6 @@ ifndef CONFIG_MIPS_GIC
|
|
|
+ obj-y += clk.o timer.o
|
|
|
+ endif
|
|
|
+
|
|
|
+-obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
|
|
|
+-
|
|
|
+ obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o
|
|
|
+
|
|
|
+ obj-$(CONFIG_IRQ_INTC) += irq.o
|
|
|
+--- a/arch/mips/ralink/cevt-rt3352.c
|
|
|
++++ /dev/null
|
|
|
+@@ -1,153 +0,0 @@
|
|
|
+-/*
|
|
|
+- * This file is subject to the terms and conditions of the GNU General Public
|
|
|
+- * License. See the file "COPYING" in the main directory of this archive
|
|
|
+- * for more details.
|
|
|
+- *
|
|
|
+- * Copyright (C) 2013 by John Crispin <[email protected]>
|
|
|
+- */
|
|
|
+-
|
|
|
+-#include <linux/clockchips.h>
|
|
|
+-#include <linux/clocksource.h>
|
|
|
+-#include <linux/interrupt.h>
|
|
|
+-#include <linux/reset.h>
|
|
|
+-#include <linux/init.h>
|
|
|
+-#include <linux/time.h>
|
|
|
+-#include <linux/of.h>
|
|
|
+-#include <linux/of_irq.h>
|
|
|
+-#include <linux/of_address.h>
|
|
|
+-
|
|
|
+-#include <asm/mach-ralink/ralink_regs.h>
|
|
|
+-
|
|
|
+-#define SYSTICK_FREQ (50 * 1000)
|
|
|
+-
|
|
|
+-#define SYSTICK_CONFIG 0x00
|
|
|
+-#define SYSTICK_COMPARE 0x04
|
|
|
+-#define SYSTICK_COUNT 0x08
|
|
|
+-
|
|
|
+-/* route systick irq to mips irq 7 instead of the r4k-timer */
|
|
|
+-#define CFG_EXT_STK_EN 0x2
|
|
|
+-/* enable the counter */
|
|
|
+-#define CFG_CNT_EN 0x1
|
|
|
+-
|
|
|
+-struct systick_device {
|
|
|
+- void __iomem *membase;
|
|
|
+- struct clock_event_device dev;
|
|
|
+- int irq_requested;
|
|
|
+- int freq_scale;
|
|
|
+-};
|
|
|
+-
|
|
|
+-static int systick_set_oneshot(struct clock_event_device *evt);
|
|
|
+-static int systick_shutdown(struct clock_event_device *evt);
|
|
|
+-
|
|
|
+-static int systick_next_event(unsigned long delta,
|
|
|
+- struct clock_event_device *evt)
|
|
|
+-{
|
|
|
+- struct systick_device *sdev;
|
|
|
+- u32 count;
|
|
|
+-
|
|
|
+- sdev = container_of(evt, struct systick_device, dev);
|
|
|
+- count = ioread32(sdev->membase + SYSTICK_COUNT);
|
|
|
+- count = (count + delta) % SYSTICK_FREQ;
|
|
|
+- iowrite32(count, sdev->membase + SYSTICK_COMPARE);
|
|
|
+-
|
|
|
+- return 0;
|
|
|
+-}
|
|
|
+-
|
|
|
+-static void systick_event_handler(struct clock_event_device *dev)
|
|
|
+-{
|
|
|
+- /* noting to do here */
|
|
|
+-}
|
|
|
+-
|
|
|
+-static irqreturn_t systick_interrupt(int irq, void *dev_id)
|
|
|
+-{
|
|
|
+- struct clock_event_device *dev = (struct clock_event_device *) dev_id;
|
|
|
+-
|
|
|
+- dev->event_handler(dev);
|
|
|
+-
|
|
|
+- return IRQ_HANDLED;
|
|
|
+-}
|
|
|
+-
|
|
|
+-static struct systick_device systick = {
|
|
|
+- .dev = {
|
|
|
+- /*
|
|
|
+- * cevt-r4k uses 300, make sure systick
|
|
|
+- * gets used if available
|
|
|
+- */
|
|
|
+- .rating = 310,
|
|
|
+- .features = CLOCK_EVT_FEAT_ONESHOT,
|
|
|
+- .set_next_event = systick_next_event,
|
|
|
+- .set_state_shutdown = systick_shutdown,
|
|
|
+- .set_state_oneshot = systick_set_oneshot,
|
|
|
+- .event_handler = systick_event_handler,
|
|
|
+- },
|
|
|
+-};
|
|
|
+-
|
|
|
+-static int systick_shutdown(struct clock_event_device *evt)
|
|
|
+-{
|
|
|
+- struct systick_device *sdev;
|
|
|
+-
|
|
|
+- sdev = container_of(evt, struct systick_device, dev);
|
|
|
+-
|
|
|
+- if (sdev->irq_requested)
|
|
|
+- free_irq(systick.dev.irq, &systick.dev);
|
|
|
+- sdev->irq_requested = 0;
|
|
|
+- iowrite32(0, systick.membase + SYSTICK_CONFIG);
|
|
|
+-
|
|
|
+- return 0;
|
|
|
+-}
|
|
|
+-
|
|
|
+-static int systick_set_oneshot(struct clock_event_device *evt)
|
|
|
+-{
|
|
|
+- const char *name = systick.dev.name;
|
|
|
+- struct systick_device *sdev;
|
|
|
+- int irq = systick.dev.irq;
|
|
|
+-
|
|
|
+- sdev = container_of(evt, struct systick_device, dev);
|
|
|
+-
|
|
|
+- if (!sdev->irq_requested) {
|
|
|
+- if (request_irq(irq, systick_interrupt,
|
|
|
+- IRQF_PERCPU | IRQF_TIMER, name, &systick.dev))
|
|
|
+- pr_err("Failed to request irq %d (%s)\n", irq, name);
|
|
|
+- }
|
|
|
+- sdev->irq_requested = 1;
|
|
|
+- iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
|
|
|
+- systick.membase + SYSTICK_CONFIG);
|
|
|
+-
|
|
|
+- return 0;
|
|
|
+-}
|
|
|
+-
|
|
|
+-static int __init ralink_systick_init(struct device_node *np)
|
|
|
+-{
|
|
|
+- int ret;
|
|
|
+-
|
|
|
+- systick.membase = of_iomap(np, 0);
|
|
|
+- if (!systick.membase)
|
|
|
+- return -ENXIO;
|
|
|
+-
|
|
|
+- systick.dev.name = np->name;
|
|
|
+- clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
|
|
|
+- systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
|
|
|
+- systick.dev.max_delta_ticks = 0x7fff;
|
|
|
+- systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
|
|
|
+- systick.dev.min_delta_ticks = 0x3;
|
|
|
+- systick.dev.irq = irq_of_parse_and_map(np, 0);
|
|
|
+- if (!systick.dev.irq) {
|
|
|
+- pr_err("%pOFn: request_irq failed", np);
|
|
|
+- return -EINVAL;
|
|
|
+- }
|
|
|
+-
|
|
|
+- ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
|
|
|
+- SYSTICK_FREQ, 301, 16,
|
|
|
+- clocksource_mmio_readl_up);
|
|
|
+- if (ret)
|
|
|
+- return ret;
|
|
|
+-
|
|
|
+- clockevents_register_device(&systick.dev);
|
|
|
+-
|
|
|
+- pr_info("%pOFn: running - mult: %d, shift: %d\n",
|
|
|
+- np, systick.dev.mult, systick.dev.shift);
|
|
|
+-
|
|
|
+- return 0;
|
|
|
+-}
|
|
|
+-
|
|
|
+-TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
|
|
|
+--- a/drivers/clocksource/Kconfig
|
|
|
++++ b/drivers/clocksource/Kconfig
|
|
|
+@@ -732,4 +732,13 @@ config GOLDFISH_TIMER
|
|
|
+ help
|
|
|
+ Support for the timer/counter of goldfish-rtc
|
|
|
+
|
|
|
++config RALINK_TIMER
|
|
|
++ bool "Ralink System Tick Counter"
|
|
|
++ depends on SOC_RT305X || SOC_MT7620 || COMPILE_TEST
|
|
|
++ select CLKSRC_MMIO
|
|
|
++ select TIMER_OF
|
|
|
++ help
|
|
|
++ Enables support for system tick counter present on
|
|
|
++ Ralink SoCs RT3352 and MT7620.
|
|
|
++
|
|
|
+ endmenu
|
|
|
+--- a/drivers/clocksource/Makefile
|
|
|
++++ b/drivers/clocksource/Makefile
|
|
|
+@@ -89,3 +89,4 @@ obj-$(CONFIG_MSC313E_TIMER) += timer-ms
|
|
|
+ obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o
|
|
|
+ obj-$(CONFIG_GXP_TIMER) += timer-gxp.o
|
|
|
+ obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o
|
|
|
++obj-$(CONFIG_RALINK_TIMER) += timer-ralink.o
|
|
|
+--- /dev/null
|
|
|
++++ b/drivers/clocksource/timer-ralink.c
|
|
|
+@@ -0,0 +1,150 @@
|
|
|
++// SPDX-License-Identifier: GPL-2.0
|
|
|
++/*
|
|
|
++ * Ralink System Tick Counter driver present on RT3352 and MT7620 SoCs.
|
|
|
++ *
|
|
|
++ * Copyright (C) 2013 by John Crispin <[email protected]>
|
|
|
++ */
|
|
|
++
|
|
|
++#include <linux/clockchips.h>
|
|
|
++#include <linux/clocksource.h>
|
|
|
++#include <linux/interrupt.h>
|
|
|
++#include <linux/reset.h>
|
|
|
++#include <linux/init.h>
|
|
|
++#include <linux/time.h>
|
|
|
++#include <linux/of.h>
|
|
|
++#include <linux/of_irq.h>
|
|
|
++#include <linux/of_address.h>
|
|
|
++
|
|
|
++#define SYSTICK_FREQ (50 * 1000)
|
|
|
++
|
|
|
++#define SYSTICK_CONFIG 0x00
|
|
|
++#define SYSTICK_COMPARE 0x04
|
|
|
++#define SYSTICK_COUNT 0x08
|
|
|
++
|
|
|
++/* route systick irq to mips irq 7 instead of the r4k-timer */
|
|
|
++#define CFG_EXT_STK_EN 0x2
|
|
|
++/* enable the counter */
|
|
|
++#define CFG_CNT_EN 0x1
|
|
|
++
|
|
|
++struct systick_device {
|
|
|
++ void __iomem *membase;
|
|
|
++ struct clock_event_device dev;
|
|
|
++ int irq_requested;
|
|
|
++ int freq_scale;
|
|
|
++};
|
|
|
++
|
|
|
++static int systick_set_oneshot(struct clock_event_device *evt);
|
|
|
++static int systick_shutdown(struct clock_event_device *evt);
|
|
|
++
|
|
|
++static int systick_next_event(unsigned long delta,
|
|
|
++ struct clock_event_device *evt)
|
|
|
++{
|
|
|
++ struct systick_device *sdev;
|
|
|
++ u32 count;
|
|
|
++
|
|
|
++ sdev = container_of(evt, struct systick_device, dev);
|
|
|
++ count = ioread32(sdev->membase + SYSTICK_COUNT);
|
|
|
++ count = (count + delta) % SYSTICK_FREQ;
|
|
|
++ iowrite32(count, sdev->membase + SYSTICK_COMPARE);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static void systick_event_handler(struct clock_event_device *dev)
|
|
|
++{
|
|
|
++ /* noting to do here */
|
|
|
++}
|
|
|
++
|
|
|
++static irqreturn_t systick_interrupt(int irq, void *dev_id)
|
|
|
++{
|
|
|
++ struct clock_event_device *dev = (struct clock_event_device *)dev_id;
|
|
|
++
|
|
|
++ dev->event_handler(dev);
|
|
|
++
|
|
|
++ return IRQ_HANDLED;
|
|
|
++}
|
|
|
++
|
|
|
++static struct systick_device systick = {
|
|
|
++ .dev = {
|
|
|
++ /*
|
|
|
++ * cevt-r4k uses 300, make sure systick
|
|
|
++ * gets used if available
|
|
|
++ */
|
|
|
++ .rating = 310,
|
|
|
++ .features = CLOCK_EVT_FEAT_ONESHOT,
|
|
|
++ .set_next_event = systick_next_event,
|
|
|
++ .set_state_shutdown = systick_shutdown,
|
|
|
++ .set_state_oneshot = systick_set_oneshot,
|
|
|
++ .event_handler = systick_event_handler,
|
|
|
++ },
|
|
|
++};
|
|
|
++
|
|
|
++static int systick_shutdown(struct clock_event_device *evt)
|
|
|
++{
|
|
|
++ struct systick_device *sdev;
|
|
|
++
|
|
|
++ sdev = container_of(evt, struct systick_device, dev);
|
|
|
++
|
|
|
++ if (sdev->irq_requested)
|
|
|
++ free_irq(systick.dev.irq, &systick.dev);
|
|
|
++ sdev->irq_requested = 0;
|
|
|
++ iowrite32(0, systick.membase + SYSTICK_CONFIG);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static int systick_set_oneshot(struct clock_event_device *evt)
|
|
|
++{
|
|
|
++ const char *name = systick.dev.name;
|
|
|
++ struct systick_device *sdev;
|
|
|
++ int irq = systick.dev.irq;
|
|
|
++
|
|
|
++ sdev = container_of(evt, struct systick_device, dev);
|
|
|
++
|
|
|
++ if (!sdev->irq_requested) {
|
|
|
++ if (request_irq(irq, systick_interrupt,
|
|
|
++ IRQF_PERCPU | IRQF_TIMER, name, &systick.dev))
|
|
|
++ pr_err("Failed to request irq %d (%s)\n", irq, name);
|
|
|
++ }
|
|
|
++ sdev->irq_requested = 1;
|
|
|
++ iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
|
|
|
++ systick.membase + SYSTICK_CONFIG);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static int __init ralink_systick_init(struct device_node *np)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++
|
|
|
++ systick.membase = of_iomap(np, 0);
|
|
|
++ if (!systick.membase)
|
|
|
++ return -ENXIO;
|
|
|
++
|
|
|
++ systick.dev.name = np->name;
|
|
|
++ clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
|
|
|
++ systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
|
|
|
++ systick.dev.max_delta_ticks = 0x7fff;
|
|
|
++ systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
|
|
|
++ systick.dev.min_delta_ticks = 0x3;
|
|
|
++ systick.dev.irq = irq_of_parse_and_map(np, 0);
|
|
|
++ if (!systick.dev.irq) {
|
|
|
++ pr_err("%pOFn: request_irq failed", np);
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++
|
|
|
++ ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
|
|
|
++ SYSTICK_FREQ, 301, 16,
|
|
|
++ clocksource_mmio_readl_up);
|
|
|
++ if (ret)
|
|
|
++ return ret;
|
|
|
++
|
|
|
++ clockevents_register_device(&systick.dev);
|
|
|
++
|
|
|
++ pr_info("%pOFn: running - mult: %d, shift: %d\n",
|
|
|
++ np, systick.dev.mult, systick.dev.shift);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
|