OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [sparc/] [kernel/] [time.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1624 jcastillo
/* $Id: time.c,v 1.1 2005-12-20 09:50:43 jcastillo Exp $
2
 * linux/arch/sparc/kernel/time.c
3
 *
4
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5
 *
6
 * This file handles the Sparc specific time handling details.
7
 */
8
#include <linux/config.h>
9
#include <linux/errno.h>
10
#include <linux/sched.h>
11
#include <linux/kernel.h>
12
#include <linux/param.h>
13
#include <linux/string.h>
14
#include <linux/mm.h>
15
#include <linux/timex.h>
16
 
17
#include <asm/oplib.h>
18
#include <asm/segment.h>
19
#include <asm/timer.h>
20
#include <asm/mostek.h>
21
#include <asm/system.h>
22
#include <asm/irq.h>
23
#include <asm/io.h>
24
 
25
enum sparc_clock_type sp_clock_typ;
26
struct mostek48t02 *mstk48t02_regs = 0;
27
struct mostek48t08 *mstk48t08_regs = 0;
28
static int set_rtc_mmss(unsigned long);
29
 
30
/*
31
 * timer_interrupt() needs to keep up the real-time clock,
32
 * as well as call the "do_timer()" routine every clocktick
33
 */
34
void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
35
{
36
        /* last time the cmos clock got updated */
37
        static long last_rtc_update=0;
38
 
39
        clear_clock_irq();
40
 
41
        do_timer(regs);
42
 
43
        /* XXX I don't know if this is right for the Sparc yet. XXX */
44
        if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
45
            xtime.tv_usec > 500000 - (tick >> 1) &&
46
            xtime.tv_usec < 500000 + (tick >> 1))
47
          if (set_rtc_mmss(xtime.tv_sec) == 0)
48
            last_rtc_update = xtime.tv_sec;
49
          else
50
            last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
51
}
52
 
53
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
54
 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
55
 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
56
 *
57
 * [For the Julian calendar (which was used in Russia before 1917,
58
 * Britain & colonies before 1752, anywhere else before 1582,
59
 * and is still in use by some communities) leave out the
60
 * -year/100+year/400 terms, and add 10.]
61
 *
62
 * This algorithm was first published by Gauss (I think).
63
 *
64
 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
65
 * machines were long is 32-bit! (However, as time_t is signed, we
66
 * will already get problems at other places on 2038-01-19 03:14:08)
67
 */
68
static inline unsigned long mktime(unsigned int year, unsigned int mon,
69
        unsigned int day, unsigned int hour,
70
        unsigned int min, unsigned int sec)
71
{
72
        if (0 >= (int) (mon -= 2)) {     /* 1..12 -> 11,12,1..10 */
73
                mon += 12;      /* Puts Feb last since it has leap day */
74
                year -= 1;
75
        }
76
        return (((
77
            (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
78
              year*365 - 719499
79
            )*24 + hour /* now have hours */
80
           )*60 + min /* now have minutes */
81
          )*60 + sec; /* finally seconds */
82
}
83
 
84
/* Clock probing, we probe the timers here also. */
85
volatile unsigned int foo_limit;
86
 
87
static void clock_probe(void)
88
{
89
        char node_str[128];
90
        register int node, type;
91
        struct linux_prom_registers clk_reg[2];
92
 
93
        /* This will basically traverse the node-tree of the prom to see
94
         * which timer chip is on this machine.
95
         */
96
        node = 0;
97
        if(sparc_cpu_model == sun4) {
98
                printk("clock_probe: No SUN4 Clock/Timer support yet...\n");
99
                return;
100
        }
101
        if(sparc_cpu_model == sun4c)
102
                node = prom_getchild(prom_root_node);
103
        else
104
                if(sparc_cpu_model == sun4m)
105
                        node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
106
        type = 0;
107
        sp_clock_typ = MSTK_INVALID;
108
        for(;;) {
109
                prom_getstring(node, "model", node_str, sizeof(node_str));
110
                if(strcmp(node_str, "mk48t02") == 0) {
111
                        sp_clock_typ = MSTK48T02;
112
                        if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
113
                                printk("clock_probe: FAILED!\n");
114
                                halt();
115
                        }
116
                        prom_apply_obio_ranges(clk_reg, 1);
117
                        /* Map the clock register io area read-only */
118
                        mstk48t02_regs = (struct mostek48t02 *)
119
                                sparc_alloc_io((void *) clk_reg[0].phys_addr,
120
                                               (void *) 0, sizeof(*mstk48t02_regs),
121
                                               "clock", clk_reg[0].which_io, 0x0);
122
                        mstk48t08_regs = 0;  /* To catch weirdness */
123
                        break;
124
                }
125
 
126
                if(strcmp(node_str, "mk48t08") == 0) {
127
                        sp_clock_typ = MSTK48T08;
128
                        if(prom_getproperty(node, "reg", (char *) clk_reg,
129
                                            sizeof(clk_reg)) == -1) {
130
                                printk("clock_probe: FAILED!\n");
131
                                halt();
132
                        }
133
                        prom_apply_obio_ranges(clk_reg, 1);
134
                        /* Map the clock register io area read-only */
135
                        mstk48t08_regs = (struct mostek48t08 *)
136
                                sparc_alloc_io((void *) clk_reg[0].phys_addr,
137
                                               (void *) 0, sizeof(*mstk48t08_regs),
138
                                               "clock", clk_reg[0].which_io, 0x0);
139
 
140
                        mstk48t02_regs = &mstk48t08_regs->regs;
141
                        break;
142
                }
143
 
144
                node = prom_getsibling(node);
145
                if(node == 0) {
146
                        printk("Aieee, could not find timer chip type\n");
147
                        return;
148
                }
149
        }
150
}
151
 
152
#ifndef BCD_TO_BIN
153
#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
154
#endif
155
 
156
#ifndef BIN_TO_BCD
157
#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
158
#endif
159
 
160
void time_init(void)
161
{
162
        unsigned int year, mon, day, hour, min, sec;
163
        struct mostek48t02 *mregs;
164
 
165
#if CONFIG_AP1000
166
        init_timers(timer_interrupt);
167
        return;
168
#endif
169
 
170
        clock_probe();
171
        init_timers(timer_interrupt);
172
 
173
        mregs = mstk48t02_regs;
174
        if(!mregs) {
175
                prom_printf("Something wrong, clock regs not mapped yet.\n");
176
                prom_halt();
177
        }
178
        mregs->creg |= MSTK_CREG_READ;
179
        sec = BCD_TO_BIN(mregs->sec);
180
        min = BCD_TO_BIN(mregs->min);
181
        hour = BCD_TO_BIN(mregs->hour);
182
        day = BCD_TO_BIN(mregs->dom);
183
        mon = BCD_TO_BIN(mregs->mnth);
184
        year = (BCD_TO_BIN(mregs->yr) + MSTK_YR_ZERO);
185
        xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
186
        xtime.tv_usec = 0;
187
        mregs->creg &= ~MSTK_CREG_READ;
188
        return;
189
}
190
 
191
/* Nothing fancy on the Sparc yet. */
192
void do_gettimeofday(struct timeval *tv)
193
{
194
        unsigned long flags;
195
 
196
        save_flags(flags);
197
        cli();
198
#if CONFIG_AP1000
199
        ap_gettimeofday(&xtime);
200
#endif
201
        *tv = xtime;
202
        restore_flags(flags);
203
}
204
 
205
void do_settimeofday(struct timeval *tv)
206
{
207
        cli();
208
        xtime = *tv;
209
        time_state = TIME_BAD;
210
        time_maxerror = 0x70000000;
211
        time_esterror = 0x70000000;
212
        sti();
213
}
214
 
215
static int set_rtc_mmss(unsigned long nowtime)
216
{
217
        int retval = 0;
218
        int real_seconds, real_minutes, mostek_minutes;
219
        struct mostek48t02 *mregs = mstk48t02_regs;
220
 
221
        if(!mregs)
222
                retval = -1;
223
        else {
224
                mregs->creg |= MSTK_CREG_READ;
225
                mostek_minutes = BCD_TO_BIN(mregs->min);
226
                mregs->creg &= ~MSTK_CREG_READ;
227
 
228
                real_seconds = nowtime % 60;
229
                real_minutes = nowtime / 60;
230
                if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
231
                        real_minutes += 30;
232
                real_minutes %= 60;
233
                if (abs(real_minutes - mostek_minutes) < 30) {
234
                        mregs->creg |= MSTK_CREG_WRITE;
235
                        mregs->sec = real_seconds;
236
                        mregs->min = real_minutes;
237
                        mregs->creg &= ~MSTK_CREG_WRITE;
238
                } else
239
                        retval = -1;
240
        }
241
 
242
        return retval;
243
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.