diff options
Diffstat (limited to 'drivers/clocksource/meson6_timer.c')
-rw-r--r-- | drivers/clocksource/meson6_timer.c | 178 |
1 files changed, 0 insertions, 178 deletions
diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c deleted file mode 100644 index 92f20991a937..000000000000 --- a/drivers/clocksource/meson6_timer.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Amlogic Meson6 SoCs timer handling. - * - * Copyright (C) 2014 Carlo Caione <carlo@caione.org> - * - * Based on code from Amlogic, Inc - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/clk.h> -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/irqreturn.h> -#include <linux/sched_clock.h> -#include <linux/of.h> -#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 - -static void __iomem *timer_base; - -static u64 notrace meson6_timer_sched_read(void) -{ - return (u64)readl(timer_base + TIMER_ISA_VAL(CSD_ID)); -} - -static void meson6_clkevt_time_stop(unsigned char timer) -{ - u32 val = readl(timer_base + TIMER_ISA_MUX); - - writel(val & ~TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); -} - -static void meson6_clkevt_time_setup(unsigned char timer, unsigned long delay) -{ - writel(delay, timer_base + TIMER_ISA_VAL(timer)); -} - -static void meson6_clkevt_time_start(unsigned char timer, bool periodic) -{ - u32 val = readl(timer_base + TIMER_ISA_MUX); - - if (periodic) - val |= TIMER_PERIODIC_BIT(timer); - else - val &= ~TIMER_PERIODIC_BIT(timer); - - writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); -} - -static int meson6_shutdown(struct clock_event_device *evt) -{ - meson6_clkevt_time_stop(CED_ID); - 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); - 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); - 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); - - return 0; -} - -static struct clock_event_device meson6_clockevent = { - .name = "meson6_tick", - .rating = 400, - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .set_state_shutdown = meson6_shutdown, - .set_state_periodic = meson6_set_periodic, - .set_state_oneshot = meson6_set_oneshot, - .tick_resume = meson6_shutdown, - .set_next_event = meson6_clkevt_next_event, -}; - -static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = (struct clock_event_device *)dev_id; - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction meson6_timer_irq = { - .name = "meson6_timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = meson6_timer_interrupt, - .dev_id = &meson6_clockevent, -}; - -static int __init meson6_timer_init(struct device_node *node) -{ - u32 val; - int ret, irq; - - timer_base = of_io_request_and_map(node, 0, "meson6-timer"); - if (IS_ERR(timer_base)) { - pr_err("Can't map registers\n"); - return -ENXIO; - } - - irq = irq_of_parse_and_map(node, 0); - if (irq <= 0) { - pr_err("Can't parse IRQ\n"); - return -EINVAL; - } - - /* 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); - - sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC); - clocksource_mmio_init(timer_base + TIMER_ISA_VAL(CSD_ID), 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); - - /* Stop the timer A */ - meson6_clkevt_time_stop(CED_ID); - - ret = setup_irq(irq, &meson6_timer_irq); - if (ret) { - pr_warn("failed to setup irq %d\n", irq); - return ret; - } - - meson6_clockevent.cpumask = cpu_possible_mask; - meson6_clockevent.irq = irq; - - clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC, - 1, 0xfffe); - return 0; -} -TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer", - meson6_timer_init); |