diff options
Diffstat (limited to 'arch/hexagon/kernel/time.c')
| -rw-r--r-- | arch/hexagon/kernel/time.c | 80 |
1 files changed, 32 insertions, 48 deletions
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c index 9903fad997f3..6f851e1cd4ee 100644 --- a/arch/hexagon/kernel/time.c +++ b/arch/hexagon/kernel/time.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Time related functions for Hexagon architecture * * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. */ #include <linux/init.h> @@ -30,8 +17,11 @@ #include <linux/of_irq.h> #include <linux/module.h> -#include <asm/timer-regs.h> +#include <asm/delay.h> #include <asm/hexagon_vm.h> +#include <asm/time.h> + +#define TIMER_ENABLE BIT(0) /* * For the clocksource we need: @@ -46,6 +36,13 @@ cycles_t pcycle_freq_mhz; cycles_t thread_freq_mhz; cycles_t sleep_clk_freq; +/* + * 8x50 HDD Specs 5-8. Simulator co-sim not fixed until + * release 1.1, and then it's "adjustable" and probably not defaulted. + */ +#define RTOS_TIMER_INT 3 +#define RTOS_TIMER_REGS_ADDR 0xAB000000UL + static struct resource rtos_timer_resources[] = { { .start = RTOS_TIMER_REGS_ADDR, @@ -72,9 +69,9 @@ struct adsp_hw_timer_struct { /* Look for "TCX0" for related constants. */ static __iomem struct adsp_hw_timer_struct *rtos_timer; -static cycle_t timer_get_cycles(struct clocksource *cs) +static u64 timer_get_cycles(struct clocksource *cs) { - return (cycle_t) __vmgettime(); + return (u64) __vmgettime(); } static struct clocksource hexagon_clocksource = { @@ -93,24 +90,10 @@ static int set_next_event(unsigned long delta, struct clock_event_device *evt) iowrite32(0, &rtos_timer->clear); iowrite32(delta, &rtos_timer->match); - iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable); + iowrite32(TIMER_ENABLE, &rtos_timer->enable); return 0; } -/* - * Sets the mode (periodic, shutdown, oneshot, etc) of a timer. - */ -static void set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - switch (mode) { - case CLOCK_EVT_MODE_SHUTDOWN: - /* XXX implement me */ - default: - break; - } -} - #ifdef CONFIG_SMP /* Broadcast mechanism */ static void broadcast(const struct cpumask *mask) @@ -119,13 +102,13 @@ static void broadcast(const struct cpumask *mask) } #endif +/* XXX Implement set_state_shutdown() */ static struct clock_event_device hexagon_clockevent_dev = { .name = "clockevent", .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 400, .irq = RTOS_TIMER_INT, .set_next_event = set_next_event, - .set_mode = set_mode, #ifdef CONFIG_SMP .broadcast = broadcast, #endif @@ -146,7 +129,6 @@ void setup_percpu_clockdev(void) dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY; dummy_clock_dev->cpumask = cpumask_of(cpu); - dummy_clock_dev->mode = CLOCK_EVT_MODE_UNUSED; clockevents_register_device(dummy_clock_dev); } @@ -171,13 +153,6 @@ static irqreturn_t timer_interrupt(int irq, void *devid) return IRQ_HANDLED; } -/* This should also be pulled from devtree */ -static struct irqaction rtos_timer_intdesc = { - .handler = timer_interrupt, - .flags = IRQF_TIMER | IRQF_TRIGGER_RISING, - .name = "rtos_timer" -}; - /* * time_init_deferred - called by start_kernel to set up timer/clock source * @@ -187,18 +162,15 @@ static struct irqaction rtos_timer_intdesc = { * This runs just before the delay loop is calibrated, and * is used for delay calibration. */ -void __init time_init_deferred(void) +static void __init time_init_deferred(void) { struct resource *resource = NULL; struct clock_event_device *ce_dev = &hexagon_clockevent_dev; - struct device_node *dn; - struct resource r; - int err; + unsigned long flag = IRQF_TIMER | IRQF_TRIGGER_RISING; ce_dev->cpumask = cpu_all_mask; - if (!resource) - resource = rtos_timer_device.resource; + resource = rtos_timer_device.resource; /* ioremap here means this has to run later, after paging init */ rtos_timer = ioremap(resource->start, resource_size(resource)); @@ -217,14 +189,17 @@ void __init time_init_deferred(void) clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4); ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev); + ce_dev->max_delta_ticks = 0x7fffffff; ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev); + ce_dev->min_delta_ticks = 0xf; #ifdef CONFIG_SMP setup_percpu_clockdev(); #endif clockevents_register_device(ce_dev); - setup_irq(ce_dev->irq, &rtos_timer_intdesc); + if (request_irq(ce_dev->irq, timer_interrupt, flag, "rtos_timer", NULL)) + pr_err("Failed to register rtos_timer interrupt\n"); } void __init time_init(void) @@ -232,6 +207,15 @@ void __init time_init(void) late_time_init = time_init_deferred; } +void __delay(unsigned long cycles) +{ + unsigned long long start = __vmgettime(); + + while ((__vmgettime() - start) < cycles) + cpu_relax(); +} +EXPORT_SYMBOL(__delay); + /* * This could become parametric or perhaps even computed at run-time, * but for now we take the observed simulator jitter. |
