summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/timer-ralink.c
diff options
context:
space:
mode:
authorSalah Triki <salah.triki@gmail.com>2026-09-17 14:00:52 +0100
committerJonathan Cameron <jonathan.cameron@oss.qualcomm.com>2026-09-30 18:59:55 +0100
commite8dd273d199f5bbe295a8e3d8b777c5505b6b2e1 (patch)
tree767c7e109d3e6b9ec6549e99dfec9085d01318ad /drivers/clocksource/timer-ralink.c
downloadlinux-stable-e8dd273d199f5bbe295a8e3d8b777c5505b6b2e1.tar.gz
linux-stable-e8dd273d199f5bbe295a8e3d8b777c5505b6b2e1.zip
iio: proximity: isl29501: Fix return type of isl29501_register_writegrafted
isl29501_register_write() was returning a u32 instead of an int. Since the function returns negative error codes (such as -ERANGE or return values from i2c_smbus_write_byte_data()), returning an unsigned integer type prevents callers from correctly checking for negative error conditions. Fix this by changing the function return type from u32 to int. This was found through manual code review. Fixes: 1c28799257bc ("iio: light: isl29501: Add support for the ISL29501 ToF sensor.") Signed-off-by: Salah Triki <salah.triki@gmail.com> Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Diffstat (limited to 'drivers/clocksource/timer-ralink.c')
-rw-r--r--drivers/clocksource/timer-ralink.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/clocksource/timer-ralink.c b/drivers/clocksource/timer-ralink.c
new file mode 100644
index 000000000..68434d9ed
--- /dev/null
+++ b/drivers/clocksource/timer-ralink.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ralink System Tick Counter driver present on RT3352 and MT7620 SoCs.
+ *
+ * Copyright (C) 2013 by John Crispin <john@phrozen.org>
+ */
+
+#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);
+ ret = -EINVAL;
+ goto err_iounmap;
+ }
+
+ ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
+ SYSTICK_FREQ, 301, 16,
+ clocksource_mmio_readl_up);
+ if (ret)
+ goto err_free_irq;
+
+ clockevents_register_device(&systick.dev);
+
+ pr_info("%pOFn: running - mult: %d, shift: %d\n",
+ np, systick.dev.mult, systick.dev.shift);
+
+ return 0;
+
+err_free_irq:
+ irq_dispose_mapping(systick.dev.irq);
+err_iounmap:
+ iounmap(systick.membase);
+ return ret;
+}
+
+TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);