1/*
2 * Copytight (C) 1999, 2000, 05, 06 Ralf Baechle (ralf@linux-mips.org)
3 * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
4 */
5#include <linux/bcd.h>
6#include <linux/init.h>
7#include <linux/kernel.h>
8#include <linux/sched.h>
9#include <linux/interrupt.h>
10#include <linux/kernel_stat.h>
11#include <linux/param.h>
12#include <linux/time.h>
13#include <linux/timex.h>
14#include <linux/mm.h>
15
16#include <asm/time.h>
17#include <asm/pgtable.h>
18#include <asm/sgialib.h>
19#include <asm/sn/ioc3.h>
20#include <asm/m48t35.h>
21#include <asm/sn/klconfig.h>
22#include <asm/sn/arch.h>
23#include <asm/sn/addrs.h>
24#include <asm/sn/sn_private.h>
25#include <asm/sn/sn0/ip27.h>
26#include <asm/sn/sn0/hub.h>
27
28/*
29 * This is a hack; we really need to figure these values out dynamically
30 *
31 * Since 800 ns works very well with various HUB frequencies, such as
32 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
33 *
34 * Ralf: which clock rate is used to feed the counter?
35 */
36#define NSEC_PER_CYCLE		800
37#define CYCLES_PER_SEC		(NSEC_PER_SEC/NSEC_PER_CYCLE)
38#define CYCLES_PER_JIFFY	(CYCLES_PER_SEC/HZ)
39
40#define TICK_SIZE (tick_nsec / 1000)
41
42static unsigned long ct_cur[NR_CPUS];	/* What counter should be at next timer irq */
43static long last_rtc_update;		/* Last time the rtc clock got updated */
44
45
46static unsigned int rt_timer_irq;
47
48void ip27_rt_timer_interrupt(void)
49{
50	int cpu = smp_processor_id();
51	int cpuA = cputoslice(cpu) == 0;
52	unsigned int irq = rt_timer_irq;
53
54	irq_enter();
55	write_seqlock(&xtime_lock);
56
57again:
58	LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);	/* Ack  */
59	ct_cur[cpu] += CYCLES_PER_JIFFY;
60	LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
61
62	if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
63		goto again;
64
65	kstat_this_cpu.irqs[irq]++;		/* kstat only for bootcpu? */
66
67	if (cpu == 0)
68		do_timer(1);
69
70	update_process_times(user_mode(get_irq_regs()));
71
72	/*
73	 * If we have an externally synchronized Linux clock, then update
74	 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
75	 * called as close as possible to when a second starts.
76	 */
77	if (ntp_synced() &&
78	    xtime.tv_sec > last_rtc_update + 660 &&
79	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
80	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
81		if (rtc_mips_set_time(xtime.tv_sec) == 0) {
82			last_rtc_update = xtime.tv_sec;
83		} else {
84			last_rtc_update = xtime.tv_sec - 600;
85			/* do it again in 60 s */
86		}
87	}
88
89	write_sequnlock(&xtime_lock);
90	irq_exit();
91}
92
93/* Includes for ioc3_init().  */
94#include <asm/sn/types.h>
95#include <asm/sn/sn0/addrs.h>
96#include <asm/sn/sn0/hubni.h>
97#include <asm/sn/sn0/hubio.h>
98#include <asm/pci/bridge.h>
99
100static __init unsigned long get_m48t35_time(void)
101{
102        unsigned int year, month, date, hour, min, sec;
103	struct m48t35_rtc *rtc;
104	nasid_t nid;
105
106	nid = get_nasid();
107	rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
108							IOC3_BYTEBUS_DEV0);
109
110	rtc->control |= M48T35_RTC_READ;
111	sec = rtc->sec;
112	min = rtc->min;
113	hour = rtc->hour;
114	date = rtc->date;
115	month = rtc->month;
116	year = rtc->year;
117	rtc->control &= ~M48T35_RTC_READ;
118
119        sec = BCD2BIN(sec);
120        min = BCD2BIN(min);
121        hour = BCD2BIN(hour);
122        date = BCD2BIN(date);
123        month = BCD2BIN(month);
124        year = BCD2BIN(year);
125
126        year += 1970;
127
128        return mktime(year, month, date, hour, min, sec);
129}
130
131static void enable_rt_irq(unsigned int irq)
132{
133}
134
135static void disable_rt_irq(unsigned int irq)
136{
137}
138
139static struct irq_chip rt_irq_type = {
140	.name		= "SN HUB RT timer",
141	.ack		= disable_rt_irq,
142	.mask		= disable_rt_irq,
143	.mask_ack	= disable_rt_irq,
144	.unmask		= enable_rt_irq,
145	.eoi		= enable_rt_irq,
146};
147
148static struct irqaction rt_irqaction = {
149	.handler	= (irq_handler_t) ip27_rt_timer_interrupt,
150	.flags		= IRQF_DISABLED,
151	.mask		= CPU_MASK_NONE,
152	.name		= "timer"
153};
154
155void __init plat_timer_setup(struct irqaction *irq)
156{
157	int irqno  = allocate_irqno();
158
159	if (irqno < 0)
160		panic("Can't allocate interrupt number for timer interrupt");
161
162	set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq);
163
164	/* over-write the handler, we use our own way */
165	irq->handler = no_action;
166
167	/* setup irqaction */
168	irq_desc[irqno].status |= IRQ_PER_CPU;
169
170	rt_timer_irq = irqno;
171	/*
172	 * Only needed to get /proc/interrupt to display timer irq stats
173	 */
174	setup_irq(irqno, &rt_irqaction);
175}
176
177static cycle_t ip27_hpt_read(void)
178{
179	return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
180}
181
182void __init ip27_time_init(void)
183{
184	clocksource_mips.read = ip27_hpt_read;
185	mips_hpt_frequency = CYCLES_PER_SEC;
186	xtime.tv_sec = get_m48t35_time();
187	xtime.tv_nsec = 0;
188}
189
190void __init cpu_time_init(void)
191{
192	lboard_t *board;
193	klcpu_t *cpu;
194	int cpuid;
195
196	/* Don't use ARCS.  ARCS is fragile.  Klconfig is simple and sane.  */
197	board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27);
198	if (!board)
199		panic("Can't find board info for myself.");
200
201	cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX;
202	cpu = (klcpu_t *) KLCF_COMP(board, cpuid);
203	if (!cpu)
204		panic("No information about myself?");
205
206	printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed);
207
208	set_c0_status(SRB_TIMOCLK);
209}
210
211void __init hub_rtc_init(cnodeid_t cnode)
212{
213	/*
214	 * We only need to initialize the current node.
215	 * If this is not the current node then it is a cpuless
216	 * node and timeouts will not happen there.
217	 */
218	if (get_compact_nodeid() == cnode) {
219		int cpu = smp_processor_id();
220		LOCAL_HUB_S(PI_RT_EN_A, 1);
221		LOCAL_HUB_S(PI_RT_EN_B, 1);
222		LOCAL_HUB_S(PI_PROF_EN_A, 0);
223		LOCAL_HUB_S(PI_PROF_EN_B, 0);
224		ct_cur[cpu] = CYCLES_PER_JIFFY;
225		LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
226		LOCAL_HUB_S(PI_RT_COUNT, 0);
227		LOCAL_HUB_S(PI_RT_PEND_A, 0);
228		LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
229		LOCAL_HUB_S(PI_RT_COUNT, 0);
230		LOCAL_HUB_S(PI_RT_PEND_B, 0);
231	}
232}
233