ARM: dts: dir685: Drop spi-cpol from the display
[sfrench/cifs-2.6.git] / arch / arm / mach-ks8695 / time.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * arch/arm/mach-ks8695/time.c
4  *
5  * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
6  * Copyright (C) 2006 Simtec Electronics
7  */
8
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/irq.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/io.h>
15 #include <linux/clockchips.h>
16
17 #include <asm/mach/time.h>
18 #include <asm/system_misc.h>
19
20 #include <mach/regs-irq.h>
21
22 #include "generic.h"
23
24 #define KS8695_TMR_OFFSET       (0xF0000 + 0xE400)
25 #define KS8695_TMR_VA           (KS8695_IO_VA + KS8695_TMR_OFFSET)
26 #define KS8695_TMR_PA           (KS8695_IO_PA + KS8695_TMR_OFFSET)
27
28 /*
29  * Timer registers
30  */
31 #define KS8695_TMCON            (0x00)          /* Timer Control Register */
32 #define KS8695_T1TC             (0x04)          /* Timer 1 Timeout Count Register */
33 #define KS8695_T0TC             (0x08)          /* Timer 0 Timeout Count Register */
34 #define KS8695_T1PD             (0x0C)          /* Timer 1 Pulse Count Register */
35 #define KS8695_T0PD             (0x10)          /* Timer 0 Pulse Count Register */
36
37 /* Timer Control Register */
38 #define TMCON_T1EN              (1 << 1)        /* Timer 1 Enable */
39 #define TMCON_T0EN              (1 << 0)        /* Timer 0 Enable */
40
41 /* Timer0 Timeout Counter Register */
42 #define T0TC_WATCHDOG           (0xff)          /* Enable watchdog mode */
43
44 static int ks8695_set_periodic(struct clock_event_device *evt)
45 {
46         u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ);
47         u32 half = DIV_ROUND_CLOSEST(rate, 2);
48         u32 tmcon;
49
50         /* Disable timer 1 */
51         tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
52         tmcon &= ~TMCON_T1EN;
53         writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
54
55         /* Both registers need to count down */
56         writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
57         writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
58
59         /* Re-enable timer1 */
60         tmcon |= TMCON_T1EN;
61         writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
62         return 0;
63 }
64
65 static int ks8695_set_next_event(unsigned long cycles,
66                                  struct clock_event_device *evt)
67
68 {
69         u32 half = DIV_ROUND_CLOSEST(cycles, 2);
70         u32 tmcon;
71
72         /* Disable timer 1 */
73         tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
74         tmcon &= ~TMCON_T1EN;
75         writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
76
77         /* Both registers need to count down */
78         writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
79         writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
80
81         /* Re-enable timer1 */
82         tmcon |= TMCON_T1EN;
83         writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
84
85         return 0;
86 }
87
88 static struct clock_event_device clockevent_ks8695 = {
89         .name                   = "ks8695_t1tc",
90         /* Reasonably fast and accurate clock event */
91         .rating                 = 300,
92         .features               = CLOCK_EVT_FEAT_ONESHOT |
93                                   CLOCK_EVT_FEAT_PERIODIC,
94         .set_next_event         = ks8695_set_next_event,
95         .set_state_periodic     = ks8695_set_periodic,
96 };
97
98 /*
99  * IRQ handler for the timer.
100  */
101 static irqreturn_t ks8695_timer_interrupt(int irq, void *dev_id)
102 {
103         struct clock_event_device *evt = &clockevent_ks8695;
104
105         evt->event_handler(evt);
106         return IRQ_HANDLED;
107 }
108
109 static struct irqaction ks8695_timer_irq = {
110         .name           = "ks8695_tick",
111         .flags          = IRQF_TIMER,
112         .handler        = ks8695_timer_interrupt,
113 };
114
115 static void ks8695_timer_setup(void)
116 {
117         unsigned long tmcon;
118
119         /* Disable timer 0 and 1 */
120         tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
121         tmcon &= ~TMCON_T0EN;
122         tmcon &= ~TMCON_T1EN;
123         writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
124
125         /*
126          * Use timer 1 to fire IRQs on the timeline, minimum 2 cycles
127          * (one on each counter) maximum 2*2^32, but the API will only
128          * accept up to a 32bit full word (0xFFFFFFFFU).
129          */
130         clockevents_config_and_register(&clockevent_ks8695,
131                                         KS8695_CLOCK_RATE, 2,
132                                         0xFFFFFFFFU);
133 }
134
135 void __init ks8695_timer_init(void)
136 {
137         ks8695_timer_setup();
138
139         /* Enable timer interrupts */
140         setup_irq(KS8695_IRQ_TIMER1, &ks8695_timer_irq);
141 }
142
143 void ks8695_restart(enum reboot_mode reboot_mode, const char *cmd)
144 {
145         unsigned int reg;
146
147         if (reboot_mode == REBOOT_SOFT)
148                 soft_restart(0);
149
150         /* disable timer0 */
151         reg = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
152         writel_relaxed(reg & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
153
154         /* enable watchdog mode */
155         writel_relaxed((10 << 8) | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
156
157         /* re-enable timer0 */
158         writel_relaxed(reg | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
159 }