Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

plat-orion: share time handling code

Split off Orion time handling code into plat-orion/.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Reviewed-by: Tzachi Perelstein <tzachi@marvell.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Nicolas Pitre <nico@marvell.com>

authored by

Lennert Buytenhek and committed by
Nicolas Pitre
2bac1de2 abc0197d

+245 -192
+1 -1
arch/arm/mach-orion/Makefile
··· 1 - obj-y += common.o addr-map.o pci.o gpio.o irq.o time.o 1 + obj-y += common.o addr-map.o pci.o gpio.o irq.o 2 2 obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o 3 3 obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o 4 4 obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
+16
arch/arm/mach-orion/common.c
··· 23 23 #include <asm/timex.h> 24 24 #include <asm/mach/arch.h> 25 25 #include <asm/mach/map.h> 26 + #include <asm/mach/time.h> 26 27 #include <asm/arch/hardware.h> 28 + #include <asm/arch/orion.h> 27 29 #include <asm/arch/platform.h> 30 + #include <asm/plat-orion/time.h> 28 31 #include "common.h" 29 32 30 33 /***************************************************************************** ··· 297 294 orion_sata.dev.platform_data = sata_data; 298 295 platform_device_register(&orion_sata); 299 296 } 297 + 298 + /***************************************************************************** 299 + * Time handling 300 + ****************************************************************************/ 301 + 302 + static void orion_timer_init(void) 303 + { 304 + orion_time_init(IRQ_ORION_BRIDGE, ORION_TCLK); 305 + } 306 + 307 + struct sys_timer orion_timer = { 308 + .init = orion_timer_init, 309 + }; 300 310 301 311 /***************************************************************************** 302 312 * General
+1 -5
arch/arm/mach-orion/common.h
··· 8 8 void __init orion_map_io(void); 9 9 void __init orion_init_irq(void); 10 10 void __init orion_init(void); 11 + extern struct sys_timer orion_timer; 11 12 12 13 /* 13 14 * Enumerations and functions for Orion windows mapping. Used by Orion core ··· 56 55 57 56 void __init orion_gpio_set_valid_pins(u32 pins); 58 57 void gpio_display(void); /* debug */ 59 - 60 - /* 61 - * Orion system timer (clocksource + clockevnt, /mach-orion/time.c) 62 - */ 63 - extern struct sys_timer orion_timer; 64 58 65 59 /* 66 60 * Pull in Orion Ethernet platform_data, used by machine-setup
-181
arch/arm/mach-orion/time.c
··· 1 - /* 2 - * arch/arm/mach-orion/time.c 3 - * 4 - * Core time functions for Marvell Orion System On Chip 5 - * 6 - * Maintainer: Tzachi Perelstein <tzachi@marvell.com> 7 - * 8 - * This file is licensed under the terms of the GNU General Public 9 - * License version 2. This program is licensed "as is" without any 10 - * warranty of any kind, whether express or implied. 11 - */ 12 - 13 - #include <linux/kernel.h> 14 - #include <linux/clockchips.h> 15 - #include <linux/interrupt.h> 16 - #include <linux/irq.h> 17 - #include <asm/mach/time.h> 18 - #include <asm/arch/orion.h> 19 - #include "common.h" 20 - 21 - /* 22 - * Timer0: clock_event_device, Tick. 23 - * Timer1: clocksource, Free running. 24 - * WatchDog: Not used. 25 - * 26 - * Timers are counting down. 27 - */ 28 - #define CLOCKEVENT 0 29 - #define CLOCKSOURCE 1 30 - 31 - /* 32 - * Timers bits 33 - */ 34 - #define BRIDGE_INT_TIMER(x) (1 << ((x) + 1)) 35 - #define TIMER_EN(x) (1 << ((x) * 2)) 36 - #define TIMER_RELOAD_EN(x) (1 << (((x) * 2) + 1)) 37 - #define BRIDGE_INT_TIMER_WD (1 << 3) 38 - #define TIMER_WD_EN (1 << 4) 39 - #define TIMER_WD_RELOAD_EN (1 << 5) 40 - 41 - static cycle_t orion_clksrc_read(void) 42 - { 43 - return (0xffffffff - orion_read(TIMER_VAL(CLOCKSOURCE))); 44 - } 45 - 46 - static struct clocksource orion_clksrc = { 47 - .name = "orion_clocksource", 48 - .shift = 20, 49 - .rating = 300, 50 - .read = orion_clksrc_read, 51 - .mask = CLOCKSOURCE_MASK(32), 52 - .flags = CLOCK_SOURCE_IS_CONTINUOUS, 53 - }; 54 - 55 - static int 56 - orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) 57 - { 58 - unsigned long flags; 59 - 60 - if (delta == 0) 61 - return -ETIME; 62 - 63 - local_irq_save(flags); 64 - 65 - /* 66 - * Clear and enable timer interrupt bit 67 - */ 68 - orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); 69 - orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); 70 - 71 - /* 72 - * Setup new timer value 73 - */ 74 - orion_write(TIMER_VAL(CLOCKEVENT), delta); 75 - 76 - /* 77 - * Disable auto reload and kickoff the timer 78 - */ 79 - orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT)); 80 - orion_setbits(TIMER_CTRL, TIMER_EN(CLOCKEVENT)); 81 - 82 - local_irq_restore(flags); 83 - 84 - return 0; 85 - } 86 - 87 - static void 88 - orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) 89 - { 90 - unsigned long flags; 91 - 92 - local_irq_save(flags); 93 - 94 - if (mode == CLOCK_EVT_MODE_PERIODIC) { 95 - /* 96 - * Setup latch cycles in timer and enable reload interrupt. 97 - */ 98 - orion_write(TIMER_VAL_RELOAD(CLOCKEVENT), LATCH); 99 - orion_write(TIMER_VAL(CLOCKEVENT), LATCH); 100 - orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); 101 - orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) | 102 - TIMER_EN(CLOCKEVENT)); 103 - } else { 104 - /* 105 - * Disable timer and interrupt 106 - */ 107 - orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); 108 - orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); 109 - orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) | 110 - TIMER_EN(CLOCKEVENT)); 111 - } 112 - 113 - local_irq_restore(flags); 114 - } 115 - 116 - static struct clock_event_device orion_clkevt = { 117 - .name = "orion_tick", 118 - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 119 - .shift = 32, 120 - .rating = 300, 121 - .cpumask = CPU_MASK_CPU0, 122 - .set_next_event = orion_clkevt_next_event, 123 - .set_mode = orion_clkevt_mode, 124 - }; 125 - 126 - static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) 127 - { 128 - /* 129 - * Clear cause bit and do event 130 - */ 131 - orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); 132 - orion_clkevt.event_handler(&orion_clkevt); 133 - return IRQ_HANDLED; 134 - } 135 - 136 - static struct irqaction orion_timer_irq = { 137 - .name = "orion_tick", 138 - .flags = IRQF_DISABLED | IRQF_TIMER, 139 - .handler = orion_timer_interrupt 140 - }; 141 - 142 - static void orion_timer_init(void) 143 - { 144 - /* 145 - * Setup clocksource free running timer (no interrupt on reload) 146 - */ 147 - orion_write(TIMER_VAL(CLOCKSOURCE), 0xffffffff); 148 - orion_write(TIMER_VAL_RELOAD(CLOCKSOURCE), 0xffffffff); 149 - orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKSOURCE)); 150 - orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKSOURCE) | 151 - TIMER_EN(CLOCKSOURCE)); 152 - 153 - /* 154 - * Register clocksource 155 - */ 156 - orion_clksrc.mult = 157 - clocksource_hz2mult(CLOCK_TICK_RATE, orion_clksrc.shift); 158 - 159 - clocksource_register(&orion_clksrc); 160 - 161 - /* 162 - * Connect and enable tick handler 163 - */ 164 - setup_irq(IRQ_ORION_BRIDGE, &orion_timer_irq); 165 - 166 - /* 167 - * Register clockevent 168 - */ 169 - orion_clkevt.mult = 170 - div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, orion_clkevt.shift); 171 - orion_clkevt.max_delta_ns = 172 - clockevent_delta2ns(0xfffffffe, &orion_clkevt); 173 - orion_clkevt.min_delta_ns = 174 - clockevent_delta2ns(1, &orion_clkevt); 175 - 176 - clockevents_register_device(&orion_clkevt); 177 - } 178 - 179 - struct sys_timer orion_timer = { 180 - .init = orion_timer_init, 181 - };
+1 -1
arch/arm/plat-orion/Makefile
··· 2 2 # Makefile for the linux kernel. 3 3 # 4 4 5 - obj-y := irq.o pcie.o 5 + obj-y := irq.o pcie.o time.o 6 6 obj-m := 7 7 obj-n := 8 8 obj- :=
+203
arch/arm/plat-orion/time.c
··· 1 + /* 2 + * arch/arm/plat-orion/time.c 3 + * 4 + * Marvell Orion SoC timer handling. 5 + * 6 + * This file is licensed under the terms of the GNU General Public 7 + * License version 2. This program is licensed "as is" without any 8 + * warranty of any kind, whether express or implied. 9 + * 10 + * Timer 0 is used as free-running clocksource, while timer 1 is 11 + * used as clock_event_device. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/clockchips.h> 16 + #include <linux/interrupt.h> 17 + #include <linux/irq.h> 18 + #include <asm/mach/time.h> 19 + #include <asm/arch/hardware.h> 20 + 21 + /* 22 + * Number of timer ticks per jiffy. 23 + */ 24 + static u32 ticks_per_jiffy; 25 + 26 + 27 + /* 28 + * Timer block registers. 29 + */ 30 + #define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000) 31 + #define TIMER0_EN 0x0001 32 + #define TIMER0_RELOAD_EN 0x0002 33 + #define TIMER1_EN 0x0004 34 + #define TIMER1_RELOAD_EN 0x0008 35 + #define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010) 36 + #define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014) 37 + #define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018) 38 + #define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c) 39 + 40 + 41 + /* 42 + * Clocksource handling. 43 + */ 44 + static cycle_t orion_clksrc_read(void) 45 + { 46 + return 0xffffffff - readl(TIMER0_VAL); 47 + } 48 + 49 + static struct clocksource orion_clksrc = { 50 + .name = "orion_clocksource", 51 + .shift = 20, 52 + .rating = 300, 53 + .read = orion_clksrc_read, 54 + .mask = CLOCKSOURCE_MASK(32), 55 + .flags = CLOCK_SOURCE_IS_CONTINUOUS, 56 + }; 57 + 58 + 59 + 60 + /* 61 + * Clockevent handling. 62 + */ 63 + static int 64 + orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) 65 + { 66 + unsigned long flags; 67 + u32 u; 68 + 69 + if (delta == 0) 70 + return -ETIME; 71 + 72 + local_irq_save(flags); 73 + 74 + /* 75 + * Clear and enable clockevent timer interrupt. 76 + */ 77 + writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE); 78 + 79 + u = readl(BRIDGE_MASK); 80 + u |= BRIDGE_INT_TIMER1; 81 + writel(u, BRIDGE_MASK); 82 + 83 + /* 84 + * Setup new clockevent timer value. 85 + */ 86 + writel(delta, TIMER1_VAL); 87 + 88 + /* 89 + * Enable the timer. 90 + */ 91 + u = readl(TIMER_CTRL); 92 + u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN; 93 + writel(u, TIMER_CTRL); 94 + 95 + local_irq_restore(flags); 96 + 97 + return 0; 98 + } 99 + 100 + static void 101 + orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) 102 + { 103 + unsigned long flags; 104 + u32 u; 105 + 106 + local_irq_save(flags); 107 + if (mode == CLOCK_EVT_MODE_PERIODIC) { 108 + /* 109 + * Setup timer to fire at 1/HZ intervals. 110 + */ 111 + writel(ticks_per_jiffy - 1, TIMER1_RELOAD); 112 + writel(ticks_per_jiffy - 1, TIMER1_VAL); 113 + 114 + /* 115 + * Enable timer interrupt. 116 + */ 117 + u = readl(BRIDGE_MASK); 118 + writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK); 119 + 120 + /* 121 + * Enable timer. 122 + */ 123 + u = readl(TIMER_CTRL); 124 + writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL); 125 + } else { 126 + /* 127 + * Disable timer. 128 + */ 129 + u = readl(TIMER_CTRL); 130 + writel(u & ~TIMER1_EN, TIMER_CTRL); 131 + 132 + /* 133 + * Disable timer interrupt. 134 + */ 135 + u = readl(BRIDGE_MASK); 136 + writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK); 137 + 138 + /* 139 + * ACK pending timer interrupt. 140 + */ 141 + writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE); 142 + 143 + } 144 + local_irq_restore(flags); 145 + } 146 + 147 + static struct clock_event_device orion_clkevt = { 148 + .name = "orion_tick", 149 + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, 150 + .shift = 32, 151 + .rating = 300, 152 + .cpumask = CPU_MASK_CPU0, 153 + .set_next_event = orion_clkevt_next_event, 154 + .set_mode = orion_clkevt_mode, 155 + }; 156 + 157 + static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) 158 + { 159 + /* 160 + * ACK timer interrupt and call event handler. 161 + */ 162 + writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE); 163 + orion_clkevt.event_handler(&orion_clkevt); 164 + 165 + return IRQ_HANDLED; 166 + } 167 + 168 + static struct irqaction orion_timer_irq = { 169 + .name = "orion_tick", 170 + .flags = IRQF_DISABLED | IRQF_TIMER, 171 + .handler = orion_timer_interrupt 172 + }; 173 + 174 + void __init orion_time_init(unsigned int irq, unsigned int tclk) 175 + { 176 + u32 u; 177 + 178 + ticks_per_jiffy = (tclk + HZ/2) / HZ; 179 + 180 + 181 + /* 182 + * Setup free-running clocksource timer (interrupts 183 + * disabled.) 184 + */ 185 + writel(0xffffffff, TIMER0_VAL); 186 + writel(0xffffffff, TIMER0_RELOAD); 187 + u = readl(BRIDGE_MASK); 188 + writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK); 189 + u = readl(TIMER_CTRL); 190 + writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL); 191 + orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift); 192 + clocksource_register(&orion_clksrc); 193 + 194 + 195 + /* 196 + * Setup clockevent timer (interrupt-driven.) 197 + */ 198 + setup_irq(irq, &orion_timer_irq); 199 + orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift); 200 + orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt); 201 + orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt); 202 + clockevents_register_device(&orion_clkevt); 203 + }
+4 -3
include/asm-arm/arch-orion/orion.h
··· 137 137 #define POWER_MNG_CTRL_REG ORION_BRIDGE_REG(0x11C) 138 138 #define BRIDGE_CAUSE ORION_BRIDGE_REG(0x110) 139 139 #define BRIDGE_MASK ORION_BRIDGE_REG(0x114) 140 + #define BRIDGE_INT_TIMER0 0x0002 141 + #define BRIDGE_INT_TIMER1 0x0004 140 142 #define MAIN_IRQ_CAUSE ORION_BRIDGE_REG(0x200) 141 143 #define MAIN_IRQ_MASK ORION_BRIDGE_REG(0x204) 142 - #define TIMER_CTRL ORION_BRIDGE_REG(0x300) 143 - #define TIMER_VAL(x) ORION_BRIDGE_REG(0x314 + ((x) * 8)) 144 - #define TIMER_VAL_RELOAD(x) ORION_BRIDGE_REG(0x310 + ((x) * 8)) 144 + 145 + #define TIMER_VIRT_BASE (ORION_BRIDGE_VIRT_BASE | 0x300) 145 146 146 147 #ifndef __ASSEMBLY__ 147 148
+2 -1
include/asm-arm/arch-orion/timex.h
··· 8 8 * warranty of any kind, whether express or implied. 9 9 */ 10 10 11 + #define CLOCK_TICK_RATE (100 * HZ) 12 + 11 13 #define ORION_TCLK 166666667 12 - #define CLOCK_TICK_RATE ORION_TCLK
+17
include/asm-arm/plat-orion/time.h
··· 1 + /* 2 + * include/asm-arm/plat-orion/time.h 3 + * 4 + * Marvell Orion SoC time handling. 5 + * 6 + * This file is licensed under the terms of the GNU General Public 7 + * License version 2. This program is licensed "as is" without any 8 + * warranty of any kind, whether express or implied. 9 + */ 10 + 11 + #ifndef __ASM_PLAT_ORION_TIME_H 12 + #define __ASM_PLAT_ORION_TIME_H 13 + 14 + void orion_time_init(unsigned int irq, unsigned int tclk); 15 + 16 + 17 + #endif