1/* 2 * arch/arm/mach-ox820/rps-time.c 3 * 4 * Copyright (C) 2009 Oxford Semiconductor Ltd 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include <linux/init.h> 20#include <linux/interrupt.h> 21#include <linux/irq.h> 22#include <linux/io.h> 23#include <linux/clockchips.h> 24#include <linux/clk.h> 25#include <linux/of_irq.h> 26#include <linux/of_address.h> 27#include <linux/sched_clock.h> 28#include <mach/hardware.h> 29 30enum { 31 TIMER_LOAD = 0, 32 TIMER_CURR = 4, 33 TIMER_CTRL = 8, 34 TIMER_CLRINT = 0xC, 35 36 TIMER_BITS = 24, 37 38 TIMER_MAX_VAL = (1 << TIMER_BITS) - 1, 39 40 TIMER_PERIODIC = (1 << 6), 41 TIMER_ENABLE = (1 << 7), 42 43 TIMER_DIV1 = (0 << 2), 44 TIMER_DIV16 = (1 << 2), 45 TIMER_DIV256 = (2 << 2), 46 47 TIMER1_OFFSET = 0, 48 TIMER2_OFFSET = 0x20, 49 50}; 51 52static u64 notrace rps_read_sched_clock(void) 53{ 54 return ~readl_relaxed(RPSA_TIMER2_VAL); 55} 56 57static void __init rps_clocksource_init(void __iomem *base, ulong ref_rate) 58{ 59 int ret; 60 ulong clock_rate; 61 /* use prescale 16 */ 62 clock_rate = ref_rate / 16; 63 64 iowrite32(TIMER_MAX_VAL, base + TIMER_LOAD); 65 iowrite32(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16, 66 base + TIMER_CTRL); 67 68 ret = clocksource_mmio_init(base + TIMER_CURR, "rps_clocksource_timer", 69 clock_rate, 250, TIMER_BITS, 70 clocksource_mmio_readl_down); 71 if (ret) 72 panic("can't register clocksource\n"); 73 74 sched_clock_register(rps_read_sched_clock, TIMER_BITS, clock_rate); 75} 76 77static void __init rps_timer_init(struct device_node *np) 78{ 79 struct clk *refclk; 80 unsigned long ref_rate; 81 void __iomem *base; 82 83 refclk = of_clk_get(np, 0); 84 85 if (IS_ERR(refclk) || clk_prepare_enable(refclk)) 86 panic("rps_timer_init: failed to get refclk\n"); 87 ref_rate = clk_get_rate(refclk); 88 89 base = of_iomap(np, 0); 90 if (!base) 91 panic("rps_timer_init: failed to map io\n"); 92 93 rps_clocksource_init(base + TIMER2_OFFSET, ref_rate); 94} 95 96CLOCKSOURCE_OF_DECLARE(nas782x, "plxtech,nas782x-rps-timer", rps_timer_init); 97