summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/meson6_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource/meson6_timer.c')
-rw-r--r--drivers/clocksource/meson6_timer.c108
1 files changed, 64 insertions, 44 deletions
diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c
index 92f20991a937..23c7638e2bb3 100644
--- a/drivers/clocksource/meson6_timer.c
+++ b/drivers/clocksource/meson6_timer.c
@@ -10,6 +10,8 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -20,80 +22,96 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#define CED_ID 0
-#define CSD_ID 4
-
-#define TIMER_ISA_MUX 0
-#define TIMER_ISA_VAL(t) (((t) + 1) << 2)
-
-#define TIMER_INPUT_BIT(t) (2 * (t))
-#define TIMER_ENABLE_BIT(t) (16 + (t))
-#define TIMER_PERIODIC_BIT(t) (12 + (t))
-
-#define TIMER_CED_INPUT_MASK (3UL << TIMER_INPUT_BIT(CED_ID))
-#define TIMER_CSD_INPUT_MASK (7UL << TIMER_INPUT_BIT(CSD_ID))
-
-#define TIMER_CED_UNIT_1US 0
-#define TIMER_CSD_UNIT_1US 1
+#define MESON_ISA_TIMER_MUX 0x00
+#define MESON_ISA_TIMER_MUX_TIMERD_EN BIT(19)
+#define MESON_ISA_TIMER_MUX_TIMERC_EN BIT(18)
+#define MESON_ISA_TIMER_MUX_TIMERB_EN BIT(17)
+#define MESON_ISA_TIMER_MUX_TIMERA_EN BIT(16)
+#define MESON_ISA_TIMER_MUX_TIMERD_MODE BIT(15)
+#define MESON_ISA_TIMER_MUX_TIMERC_MODE BIT(14)
+#define MESON_ISA_TIMER_MUX_TIMERB_MODE BIT(13)
+#define MESON_ISA_TIMER_MUX_TIMERA_MODE BIT(12)
+#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK GENMASK(10, 8)
+#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_SYSTEM_CLOCK 0x0
+#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US 0x1
+#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_10US 0x2
+#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_100US 0x3
+#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1MS 0x4
+#define MESON_ISA_TIMER_MUX_TIMERD_INPUT_CLOCK_MASK GENMASK(7, 6)
+#define MESON_ISA_TIMER_MUX_TIMERC_INPUT_CLOCK_MASK GENMASK(5, 4)
+#define MESON_ISA_TIMER_MUX_TIMERB_INPUT_CLOCK_MASK GENMASK(3, 2)
+#define MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK GENMASK(1, 0)
+#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US 0x0
+#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_10US 0x1
+#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_100US 0x0
+#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1MS 0x3
+
+#define MESON_ISA_TIMERA 0x04
+#define MESON_ISA_TIMERB 0x08
+#define MESON_ISA_TIMERC 0x0c
+#define MESON_ISA_TIMERD 0x10
+#define MESON_ISA_TIMERE 0x14
static void __iomem *timer_base;
static u64 notrace meson6_timer_sched_read(void)
{
- return (u64)readl(timer_base + TIMER_ISA_VAL(CSD_ID));
+ return (u64)readl(timer_base + MESON_ISA_TIMERE);
}
-static void meson6_clkevt_time_stop(unsigned char timer)
+static void meson6_clkevt_time_stop(void)
{
- u32 val = readl(timer_base + TIMER_ISA_MUX);
+ u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
- writel(val & ~TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX);
+ writel(val & ~MESON_ISA_TIMER_MUX_TIMERA_EN,
+ timer_base + MESON_ISA_TIMER_MUX);
}
-static void meson6_clkevt_time_setup(unsigned char timer, unsigned long delay)
+static void meson6_clkevt_time_setup(unsigned long delay)
{
- writel(delay, timer_base + TIMER_ISA_VAL(timer));
+ writel(delay, timer_base + MESON_ISA_TIMERA);
}
-static void meson6_clkevt_time_start(unsigned char timer, bool periodic)
+static void meson6_clkevt_time_start(bool periodic)
{
- u32 val = readl(timer_base + TIMER_ISA_MUX);
+ u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
if (periodic)
- val |= TIMER_PERIODIC_BIT(timer);
+ val |= MESON_ISA_TIMER_MUX_TIMERA_MODE;
else
- val &= ~TIMER_PERIODIC_BIT(timer);
+ val &= ~MESON_ISA_TIMER_MUX_TIMERA_MODE;
- writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX);
+ writel(val | MESON_ISA_TIMER_MUX_TIMERA_EN,
+ timer_base + MESON_ISA_TIMER_MUX);
}
static int meson6_shutdown(struct clock_event_device *evt)
{
- meson6_clkevt_time_stop(CED_ID);
+ meson6_clkevt_time_stop();
return 0;
}
static int meson6_set_oneshot(struct clock_event_device *evt)
{
- meson6_clkevt_time_stop(CED_ID);
- meson6_clkevt_time_start(CED_ID, false);
+ meson6_clkevt_time_stop();
+ meson6_clkevt_time_start(false);
return 0;
}
static int meson6_set_periodic(struct clock_event_device *evt)
{
- meson6_clkevt_time_stop(CED_ID);
- meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC / HZ - 1);
- meson6_clkevt_time_start(CED_ID, true);
+ meson6_clkevt_time_stop();
+ meson6_clkevt_time_setup(USEC_PER_SEC / HZ - 1);
+ meson6_clkevt_time_start(true);
return 0;
}
static int meson6_clkevt_next_event(unsigned long evt,
struct clock_event_device *unused)
{
- meson6_clkevt_time_stop(CED_ID);
- meson6_clkevt_time_setup(CED_ID, evt);
- meson6_clkevt_time_start(CED_ID, false);
+ meson6_clkevt_time_stop();
+ meson6_clkevt_time_setup(evt);
+ meson6_clkevt_time_start(false);
return 0;
}
@@ -144,22 +162,24 @@ static int __init meson6_timer_init(struct device_node *node)
}
/* Set 1us for timer E */
- val = readl(timer_base + TIMER_ISA_MUX);
- val &= ~TIMER_CSD_INPUT_MASK;
- val |= TIMER_CSD_UNIT_1US << TIMER_INPUT_BIT(CSD_ID);
- writel(val, timer_base + TIMER_ISA_MUX);
+ val = readl(timer_base + MESON_ISA_TIMER_MUX);
+ val &= ~MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK;
+ val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK,
+ MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US);
+ writel(val, timer_base + MESON_ISA_TIMER_MUX);
sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC);
- clocksource_mmio_init(timer_base + TIMER_ISA_VAL(CSD_ID), node->name,
+ clocksource_mmio_init(timer_base + MESON_ISA_TIMERE, node->name,
1000 * 1000, 300, 32, clocksource_mmio_readl_up);
/* Timer A base 1us */
- val &= ~TIMER_CED_INPUT_MASK;
- val |= TIMER_CED_UNIT_1US << TIMER_INPUT_BIT(CED_ID);
- writel(val, timer_base + TIMER_ISA_MUX);
+ val &= ~MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK;
+ val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK,
+ MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US);
+ writel(val, timer_base + MESON_ISA_TIMER_MUX);
/* Stop the timer A */
- meson6_clkevt_time_stop(CED_ID);
+ meson6_clkevt_time_stop();
ret = setup_irq(irq, &meson6_timer_irq);
if (ret) {
OpenPOWER on IntegriCloud