1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/config.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/tty.h>
20#include <linux/console.h>
21#include <linux/linkage.h>
22#include <linux/init.h>
23#include <linux/major.h>
24#include <linux/serial_reg.h>
25#include <linux/rtc.h>
26#include <linux/vt_kern.h>
27
28#include <asm/io.h>
29#include <asm/rtc.h>
30#include <asm/bootinfo.h>
31#include <asm/system.h>
32#include <asm/pgtable.h>
33#include <asm/setup.h>
34#include <asm/irq.h>
35#include <asm/traps.h>
36#include <asm/rtc.h>
37#include <asm/machdep.h>
38#include <asm/q40_master.h>
39#include <asm/keyboard.h>
40
41extern void floppy_setup(char *str, int *ints);
42
43extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
44 char raw_mode);
45extern void q40_process_int (int level, struct pt_regs *regs);
46extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);
47extern void q40_init_IRQ (void);
48extern void q40_free_irq (unsigned int, void *);
49extern int q40_get_irq_list (char *);
50extern void q40_enable_irq (unsigned int);
51extern void q40_disable_irq (unsigned int);
52static void q40_get_model(char *model);
53static int q40_get_hardware_list(char *buffer);
54extern int q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
55extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *));
56
57extern unsigned long q40_gettimeoffset (void);
58extern void q40_gettod (int *year, int *mon, int *day, int *hour,
59 int *min, int *sec);
60extern int q40_hwclk (int, struct rtc_time *);
61extern unsigned int q40_get_ss (void);
62extern int q40_set_clock_mmss (unsigned long);
63static int q40_get_rtc_pll(struct rtc_pll_info *pll);
64static int q40_set_rtc_pll(struct rtc_pll_info *pll);
65extern void q40_reset (void);
66void q40_halt(void);
67extern void q40_waitbut(void);
68void q40_set_vectors (void);
69
70void q40_mksound(unsigned int , unsigned int );
71
72extern char *saved_command_line;
73extern char m68k_debug_device[];
74static void q40_mem_console_write(struct console *co, const char *b,
75 unsigned int count);
76
77extern int ql_ticks;
78
79static struct console q40_console_driver = {
80 name: "debug",
81 flags: CON_PRINTBUFFER,
82 index: -1,
83};
84
85
86
87extern char *q40_mem_cptr;
88static int _cpleft;
89
90#if 0
91int q40_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
92{
93 *keycodep = keycode;
94 return 1;
95}
96#endif
97
98static void q40_mem_console_write(struct console *co, const char *s,
99 unsigned int count)
100{
101 char *p=(char *)s;
102
103 if (count<_cpleft)
104 while (count-- >0){
105 *q40_mem_cptr=*p++;
106 q40_mem_cptr+=4;
107 _cpleft--;
108 }
109}
110#if 0
111void printq40(char *str)
112{
113 int l=strlen(str);
114 char *p=q40_mem_cptr;
115
116 while (l-- >0 && _cpleft-- >0)
117 {
118 *p=*str++;
119 p+=4;
120 }
121 q40_mem_cptr=p;
122}
123#endif
124
125#if 0
126int q40_kbdrate (struct kbd_repeat *k)
127{
128 return 0;
129}
130#endif
131
132static int halted=0;
133
134#ifdef CONFIG_HEARTBEAT
135static void q40_heartbeat(int on)
136{
137 if (halted) return;
138
139 if (on)
140 Q40_LED_ON();
141 else
142 Q40_LED_OFF();
143}
144#endif
145
146void q40_reset()
147{
148 halted=1;
149 printk ("\n\n*******************************************\n"
150 "Called q40_reset : press the RESET button!! \n"
151 "*******************************************\n");
152 Q40_LED_ON();
153 while(1) ;
154}
155void q40_halt()
156{
157 halted=1;
158 printk ("\n\n*******************\n"
159 " Called q40_halt\n"
160 "*******************\n");
161 Q40_LED_ON();
162 while(1) ;
163}
164
165static void q40_get_model(char *model)
166{
167 sprintf(model, "Q40");
168}
169
170
171
172static int q40_get_hardware_list(char *buffer)
173{
174 *buffer = '\0';
175 return 0;
176}
177
178static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
179void q40_disable_irqs(void)
180{
181 unsigned i,j;
182
183 j=0;
184 while((i=serports[j++])) outb(0,i+UART_IER);
185 master_outb(0,EXT_ENABLE_REG);
186 master_outb(0,KEY_IRQ_ENABLE_REG);
187}
188
189void __init config_q40(void)
190{
191 mach_sched_init = q40_sched_init;
192
193#ifdef CONFIG_VT
194 mach_keyb_init = q40kbd_init_hw;
195 mach_kbd_translate = q40kbd_translate;
196 kd_mksound = q40_mksound;
197#endif
198 mach_init_IRQ = q40_init_IRQ;
199 mach_gettimeoffset = q40_gettimeoffset;
200 mach_gettod = q40_gettod;
201 mach_hwclk = q40_hwclk;
202 mach_get_ss = q40_get_ss;
203 mach_get_rtc_pll = q40_get_rtc_pll;
204 mach_set_rtc_pll = q40_set_rtc_pll;
205 mach_set_clock_mmss = q40_set_clock_mmss;
206
207 mach_reset = q40_reset;
208 mach_free_irq = q40_free_irq;
209 mach_process_int = q40_process_int;
210 mach_get_irq_list = q40_get_irq_list;
211 mach_request_irq = q40_request_irq;
212 enable_irq = q40_enable_irq;
213 disable_irq = q40_disable_irq;
214 mach_default_handler = &q40_sys_default_handler;
215 mach_get_model = q40_get_model;
216 mach_get_hardware_list = q40_get_hardware_list;
217
218#ifdef CONFIG_MAGIC_SYSRQ
219 mach_sysrq_key = 0x54;
220#endif
221#ifdef CONFIG_HEARTBEAT
222 mach_heartbeat = q40_heartbeat;
223#endif
224 mach_halt = q40_halt;
225#ifdef CONFIG_DUMMY_CONSOLE
226 conswitchp = &dummy_con;
227#endif
228
229
230 q40_disable_irqs();
231
232
233
234
235 mach_max_dma_address = 1024*1024*1024;
236
237
238 if (!strncmp( m68k_debug_device,"mem",3 ))
239 {
240
241 _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
242 q40_console_driver.write = q40_mem_console_write;
243 register_console(&q40_console_driver);
244 }
245}
246
247
248int q40_parse_bootinfo(const struct bi_record *rec)
249{
250 return 1;
251}
252
253
254static inline unsigned char bcd2bin (unsigned char b)
255{
256 return ((b>>4)*10 + (b&15));
257}
258
259static inline unsigned char bin2bcd (unsigned char b)
260{
261 return (((b/10)*16) + (b%10));
262}
263
264
265unsigned long q40_gettimeoffset (void)
266{
267 return 5000*(ql_ticks!=0);
268}
269
270extern void q40_gettod (int *year, int *mon, int *day, int *hour,
271 int *min, int *sec)
272{
273 Q40_RTC_CTRL |= Q40_RTC_READ;
274 *year = bcd2bin (Q40_RTC_YEAR);
275 *mon = bcd2bin (Q40_RTC_MNTH);
276 *day = bcd2bin (Q40_RTC_DATE);
277 *hour = bcd2bin (Q40_RTC_HOUR);
278 *min = bcd2bin (Q40_RTC_MINS);
279 *sec = bcd2bin (Q40_RTC_SECS);
280 Q40_RTC_CTRL &= ~(Q40_RTC_READ);
281
282}
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301int q40_hwclk(int op, struct rtc_time *t)
302{
303 if (op)
304 {
305 Q40_RTC_CTRL |= Q40_RTC_WRITE;
306
307 Q40_RTC_SECS = bin2bcd(t->tm_sec);
308 Q40_RTC_MINS = bin2bcd(t->tm_min);
309 Q40_RTC_HOUR = bin2bcd(t->tm_hour);
310 Q40_RTC_DATE = bin2bcd(t->tm_mday);
311 Q40_RTC_MNTH = bin2bcd(t->tm_mon + 1);
312 Q40_RTC_YEAR = bin2bcd(t->tm_year%100);
313 if (t->tm_wday >= 0)
314 Q40_RTC_DOW = bin2bcd(t->tm_wday+1);
315
316 Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
317 }
318 else
319 {
320 Q40_RTC_CTRL |= Q40_RTC_READ;
321
322 t->tm_year = bcd2bin (Q40_RTC_YEAR);
323 t->tm_mon = bcd2bin (Q40_RTC_MNTH)-1;
324 t->tm_mday = bcd2bin (Q40_RTC_DATE);
325 t->tm_hour = bcd2bin (Q40_RTC_HOUR);
326 t->tm_min = bcd2bin (Q40_RTC_MINS);
327 t->tm_sec = bcd2bin (Q40_RTC_SECS);
328
329 Q40_RTC_CTRL &= ~(Q40_RTC_READ);
330
331 if (t->tm_year < 70)
332 t->tm_year += 100;
333 t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
334
335 }
336
337 return 0;
338}
339
340unsigned int q40_get_ss()
341{
342 return bcd2bin(Q40_RTC_SECS);
343}
344
345
346
347
348
349
350int q40_set_clock_mmss (unsigned long nowtime)
351{
352 int retval = 0;
353 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
354
355 int rtc_minutes;
356
357
358 rtc_minutes = bcd2bin (Q40_RTC_MINS);
359
360 if ((rtc_minutes < real_minutes
361 ? real_minutes - rtc_minutes
362 : rtc_minutes - real_minutes) < 30)
363 {
364 Q40_RTC_CTRL |= Q40_RTC_WRITE;
365 Q40_RTC_MINS = bin2bcd(real_minutes);
366 Q40_RTC_SECS = bin2bcd(real_seconds);
367 Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
368 }
369 else
370 retval = -1;
371
372
373 return retval;
374}
375
376
377
378#define Q40_RTC_PLL_MASK ((1<<5)-1)
379#define Q40_RTC_PLL_SIGN (1<<5)
380
381static int q40_get_rtc_pll(struct rtc_pll_info *pll)
382{
383 int tmp=Q40_RTC_CTRL;
384 pll->pll_value = tmp & Q40_RTC_PLL_MASK;
385 if (tmp & Q40_RTC_PLL_SIGN)
386 pll->pll_value = -pll->pll_value;
387 pll->pll_max=31;
388 pll->pll_min=-31;
389 pll->pll_posmult=512;
390 pll->pll_negmult=256;
391 pll->pll_clock=125829120;
392 return 0;
393 }
394
395static int q40_set_rtc_pll(struct rtc_pll_info *pll)
396{
397 if (!pll->pll_ctrl){
398
399 int tmp=(pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) | Q40_RTC_WRITE;
400 Q40_RTC_CTRL |= Q40_RTC_WRITE;
401 Q40_RTC_CTRL = tmp;
402 Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
403 return 0;
404 } else return -EINVAL;
405}
406