diff options
Diffstat (limited to 'arch/m68k/q40/config.c')
-rw-r--r-- | arch/m68k/q40/config.c | 272 |
1 files changed, 140 insertions, 132 deletions
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 92f873cc7060..476e18eca758 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c | |||
@@ -35,35 +35,35 @@ | |||
35 | #include <asm/machdep.h> | 35 | #include <asm/machdep.h> |
36 | #include <asm/q40_master.h> | 36 | #include <asm/q40_master.h> |
37 | 37 | ||
38 | extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); | 38 | extern irqreturn_t q40_process_int(int level, struct pt_regs *regs); |
39 | extern void q40_init_IRQ (void); | 39 | extern void q40_init_IRQ(void); |
40 | static void q40_get_model(char *model); | 40 | static void q40_get_model(char *model); |
41 | static int q40_get_hardware_list(char *buffer); | 41 | static int q40_get_hardware_list(char *buffer); |
42 | extern void q40_sched_init(irq_handler_t handler); | 42 | extern void q40_sched_init(irq_handler_t handler); |
43 | 43 | ||
44 | extern unsigned long q40_gettimeoffset (void); | 44 | extern unsigned long q40_gettimeoffset(void); |
45 | extern int q40_hwclk (int, struct rtc_time *); | 45 | extern int q40_hwclk(int, struct rtc_time *); |
46 | extern unsigned int q40_get_ss (void); | 46 | extern unsigned int q40_get_ss(void); |
47 | extern int q40_set_clock_mmss (unsigned long); | 47 | extern int q40_set_clock_mmss(unsigned long); |
48 | static int q40_get_rtc_pll(struct rtc_pll_info *pll); | 48 | static int q40_get_rtc_pll(struct rtc_pll_info *pll); |
49 | static int q40_set_rtc_pll(struct rtc_pll_info *pll); | 49 | static int q40_set_rtc_pll(struct rtc_pll_info *pll); |
50 | extern void q40_reset (void); | 50 | extern void q40_reset(void); |
51 | void q40_halt(void); | 51 | void q40_halt(void); |
52 | extern void q40_waitbut(void); | 52 | extern void q40_waitbut(void); |
53 | void q40_set_vectors (void); | 53 | void q40_set_vectors(void); |
54 | 54 | ||
55 | extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ ); | 55 | extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/); |
56 | 56 | ||
57 | extern char m68k_debug_device[]; | ||
58 | static void q40_mem_console_write(struct console *co, const char *b, | 57 | static void q40_mem_console_write(struct console *co, const char *b, |
59 | unsigned int count); | 58 | unsigned int count); |
60 | 59 | ||
61 | extern int ql_ticks; | 60 | extern int ql_ticks; |
62 | 61 | ||
63 | static struct console q40_console_driver = { | 62 | static struct console q40_console_driver = { |
64 | .name = "debug", | 63 | .name = "debug", |
65 | .flags = CON_PRINTBUFFER, | 64 | .write = q40_mem_console_write, |
66 | .index = -1, | 65 | .flags = CON_PRINTBUFFER, |
66 | .index = -1, | ||
67 | }; | 67 | }; |
68 | 68 | ||
69 | 69 | ||
@@ -74,150 +74,162 @@ static int _cpleft; | |||
74 | static void q40_mem_console_write(struct console *co, const char *s, | 74 | static void q40_mem_console_write(struct console *co, const char *s, |
75 | unsigned int count) | 75 | unsigned int count) |
76 | { | 76 | { |
77 | char *p=(char *)s; | 77 | const char *p = s; |
78 | 78 | ||
79 | if (count<_cpleft) | 79 | if (count < _cpleft) { |
80 | while (count-- >0){ | 80 | while (count-- > 0) { |
81 | *q40_mem_cptr=*p++; | 81 | *q40_mem_cptr = *p++; |
82 | q40_mem_cptr+=4; | 82 | q40_mem_cptr += 4; |
83 | _cpleft--; | 83 | _cpleft--; |
84 | } | 84 | } |
85 | } | ||
86 | } | ||
87 | |||
88 | static int __init q40_debug_setup(char *arg) | ||
89 | { | ||
90 | /* useful for early debugging stages - writes kernel messages into SRAM */ | ||
91 | if (MACH_IS_Q40 && !strncmp(arg, "mem", 3)) { | ||
92 | /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/ | ||
93 | _cpleft = 2000 - ((long)q40_mem_cptr-0xff020000) / 4; | ||
94 | register_console(&q40_console_driver); | ||
95 | } | ||
96 | return 0; | ||
85 | } | 97 | } |
98 | |||
99 | early_param("debug", q40_debug_setup); | ||
100 | |||
86 | #if 0 | 101 | #if 0 |
87 | void printq40(char *str) | 102 | void printq40(char *str) |
88 | { | 103 | { |
89 | int l=strlen(str); | 104 | int l = strlen(str); |
90 | char *p=q40_mem_cptr; | 105 | char *p = q40_mem_cptr; |
91 | 106 | ||
92 | while (l-- >0 && _cpleft-- >0) | 107 | while (l-- > 0 && _cpleft-- > 0) { |
93 | { | 108 | *p = *str++; |
94 | *p=*str++; | 109 | p += 4; |
95 | p+=4; | 110 | } |
96 | } | 111 | q40_mem_cptr = p; |
97 | q40_mem_cptr=p; | ||
98 | } | 112 | } |
99 | #endif | 113 | #endif |
100 | 114 | ||
101 | static int halted=0; | 115 | static int halted; |
102 | 116 | ||
103 | #ifdef CONFIG_HEARTBEAT | 117 | #ifdef CONFIG_HEARTBEAT |
104 | static void q40_heartbeat(int on) | 118 | static void q40_heartbeat(int on) |
105 | { | 119 | { |
106 | if (halted) return; | 120 | if (halted) |
121 | return; | ||
107 | 122 | ||
108 | if (on) | 123 | if (on) |
109 | Q40_LED_ON(); | 124 | Q40_LED_ON(); |
110 | else | 125 | else |
111 | Q40_LED_OFF(); | 126 | Q40_LED_OFF(); |
112 | } | 127 | } |
113 | #endif | 128 | #endif |
114 | 129 | ||
115 | void q40_reset(void) | 130 | void q40_reset(void) |
116 | { | 131 | { |
117 | halted=1; | 132 | halted = 1; |
118 | printk ("\n\n*******************************************\n" | 133 | printk("\n\n*******************************************\n" |
119 | "Called q40_reset : press the RESET button!! \n" | 134 | "Called q40_reset : press the RESET button!! \n" |
120 | "*******************************************\n"); | 135 | "*******************************************\n"); |
121 | Q40_LED_ON(); | 136 | Q40_LED_ON(); |
122 | while(1) ; | 137 | while (1) |
138 | ; | ||
123 | } | 139 | } |
124 | void q40_halt(void) | 140 | void q40_halt(void) |
125 | { | 141 | { |
126 | halted=1; | 142 | halted = 1; |
127 | printk ("\n\n*******************\n" | 143 | printk("\n\n*******************\n" |
128 | " Called q40_halt\n" | 144 | " Called q40_halt\n" |
129 | "*******************\n"); | 145 | "*******************\n"); |
130 | Q40_LED_ON(); | 146 | Q40_LED_ON(); |
131 | while(1) ; | 147 | while (1) |
148 | ; | ||
132 | } | 149 | } |
133 | 150 | ||
134 | static void q40_get_model(char *model) | 151 | static void q40_get_model(char *model) |
135 | { | 152 | { |
136 | sprintf(model, "Q40"); | 153 | sprintf(model, "Q40"); |
137 | } | 154 | } |
138 | 155 | ||
139 | /* No hardware options on Q40? */ | 156 | /* No hardware options on Q40? */ |
140 | 157 | ||
141 | static int q40_get_hardware_list(char *buffer) | 158 | static int q40_get_hardware_list(char *buffer) |
142 | { | 159 | { |
143 | *buffer = '\0'; | 160 | *buffer = '\0'; |
144 | return 0; | 161 | return 0; |
145 | } | 162 | } |
146 | 163 | ||
147 | static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0}; | 164 | static unsigned int serports[] = |
165 | { | ||
166 | 0x3f8,0x2f8,0x3e8,0x2e8,0 | ||
167 | }; | ||
148 | void q40_disable_irqs(void) | 168 | void q40_disable_irqs(void) |
149 | { | 169 | { |
150 | unsigned i,j; | 170 | unsigned i, j; |
151 | 171 | ||
152 | j=0; | 172 | j = 0; |
153 | while((i=serports[j++])) outb(0,i+UART_IER); | 173 | while ((i = serports[j++])) |
154 | master_outb(0,EXT_ENABLE_REG); | 174 | outb(0, i + UART_IER); |
155 | master_outb(0,KEY_IRQ_ENABLE_REG); | 175 | master_outb(0, EXT_ENABLE_REG); |
176 | master_outb(0, KEY_IRQ_ENABLE_REG); | ||
156 | } | 177 | } |
157 | 178 | ||
158 | void __init config_q40(void) | 179 | void __init config_q40(void) |
159 | { | 180 | { |
160 | mach_sched_init = q40_sched_init; | 181 | mach_sched_init = q40_sched_init; |
161 | 182 | ||
162 | mach_init_IRQ = q40_init_IRQ; | 183 | mach_init_IRQ = q40_init_IRQ; |
163 | mach_gettimeoffset = q40_gettimeoffset; | 184 | mach_gettimeoffset = q40_gettimeoffset; |
164 | mach_hwclk = q40_hwclk; | 185 | mach_hwclk = q40_hwclk; |
165 | mach_get_ss = q40_get_ss; | 186 | mach_get_ss = q40_get_ss; |
166 | mach_get_rtc_pll = q40_get_rtc_pll; | 187 | mach_get_rtc_pll = q40_get_rtc_pll; |
167 | mach_set_rtc_pll = q40_set_rtc_pll; | 188 | mach_set_rtc_pll = q40_set_rtc_pll; |
168 | mach_set_clock_mmss = q40_set_clock_mmss; | 189 | mach_set_clock_mmss = q40_set_clock_mmss; |
169 | 190 | ||
170 | mach_reset = q40_reset; | 191 | mach_reset = q40_reset; |
171 | mach_get_model = q40_get_model; | 192 | mach_get_model = q40_get_model; |
172 | mach_get_hardware_list = q40_get_hardware_list; | 193 | mach_get_hardware_list = q40_get_hardware_list; |
173 | 194 | ||
174 | #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) | 195 | #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) |
175 | mach_beep = q40_mksound; | 196 | mach_beep = q40_mksound; |
176 | #endif | 197 | #endif |
177 | #ifdef CONFIG_HEARTBEAT | 198 | #ifdef CONFIG_HEARTBEAT |
178 | mach_heartbeat = q40_heartbeat; | 199 | mach_heartbeat = q40_heartbeat; |
179 | #endif | 200 | #endif |
180 | mach_halt = q40_halt; | 201 | mach_halt = q40_halt; |
181 | 202 | ||
182 | /* disable a few things that SMSQ might have left enabled */ | 203 | /* disable a few things that SMSQ might have left enabled */ |
183 | q40_disable_irqs(); | 204 | q40_disable_irqs(); |
184 | 205 | ||
185 | /* no DMA at all, but ide-scsi requires it.. make sure | 206 | /* no DMA at all, but ide-scsi requires it.. make sure |
186 | * all physical RAM fits into the boundary - otherwise | 207 | * all physical RAM fits into the boundary - otherwise |
187 | * allocator may play costly and useless tricks */ | 208 | * allocator may play costly and useless tricks */ |
188 | mach_max_dma_address = 1024*1024*1024; | 209 | mach_max_dma_address = 1024*1024*1024; |
189 | |||
190 | /* useful for early debugging stages - writes kernel messages into SRAM */ | ||
191 | if (!strncmp( m68k_debug_device,"mem",3 )) | ||
192 | { | ||
193 | /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/ | ||
194 | _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4; | ||
195 | q40_console_driver.write = q40_mem_console_write; | ||
196 | register_console(&q40_console_driver); | ||
197 | } | ||
198 | } | 210 | } |
199 | 211 | ||
200 | 212 | ||
201 | int q40_parse_bootinfo(const struct bi_record *rec) | 213 | int q40_parse_bootinfo(const struct bi_record *rec) |
202 | { | 214 | { |
203 | return 1; | 215 | return 1; |
204 | } | 216 | } |
205 | 217 | ||
206 | 218 | ||
207 | static inline unsigned char bcd2bin (unsigned char b) | 219 | static inline unsigned char bcd2bin(unsigned char b) |
208 | { | 220 | { |
209 | return ((b>>4)*10 + (b&15)); | 221 | return (b >> 4) * 10 + (b & 15); |
210 | } | 222 | } |
211 | 223 | ||
212 | static inline unsigned char bin2bcd (unsigned char b) | 224 | static inline unsigned char bin2bcd(unsigned char b) |
213 | { | 225 | { |
214 | return (((b/10)*16) + (b%10)); | 226 | return (b / 10) * 16 + (b % 10); |
215 | } | 227 | } |
216 | 228 | ||
217 | 229 | ||
218 | unsigned long q40_gettimeoffset (void) | 230 | unsigned long q40_gettimeoffset(void) |
219 | { | 231 | { |
220 | return 5000*(ql_ticks!=0); | 232 | return 5000 * (ql_ticks != 0); |
221 | } | 233 | } |
222 | 234 | ||
223 | 235 | ||
@@ -238,9 +250,9 @@ unsigned long q40_gettimeoffset (void) | |||
238 | 250 | ||
239 | int q40_hwclk(int op, struct rtc_time *t) | 251 | int q40_hwclk(int op, struct rtc_time *t) |
240 | { | 252 | { |
241 | if (op) | 253 | if (op) { |
242 | { /* Write.... */ | 254 | /* Write.... */ |
243 | Q40_RTC_CTRL |= Q40_RTC_WRITE; | 255 | Q40_RTC_CTRL |= Q40_RTC_WRITE; |
244 | 256 | ||
245 | Q40_RTC_SECS = bin2bcd(t->tm_sec); | 257 | Q40_RTC_SECS = bin2bcd(t->tm_sec); |
246 | Q40_RTC_MINS = bin2bcd(t->tm_min); | 258 | Q40_RTC_MINS = bin2bcd(t->tm_min); |
@@ -251,25 +263,23 @@ int q40_hwclk(int op, struct rtc_time *t) | |||
251 | if (t->tm_wday >= 0) | 263 | if (t->tm_wday >= 0) |
252 | Q40_RTC_DOW = bin2bcd(t->tm_wday+1); | 264 | Q40_RTC_DOW = bin2bcd(t->tm_wday+1); |
253 | 265 | ||
254 | Q40_RTC_CTRL &= ~(Q40_RTC_WRITE); | 266 | Q40_RTC_CTRL &= ~(Q40_RTC_WRITE); |
255 | } | 267 | } else { |
256 | else | 268 | /* Read.... */ |
257 | { /* Read.... */ | 269 | Q40_RTC_CTRL |= Q40_RTC_READ; |
258 | Q40_RTC_CTRL |= Q40_RTC_READ; | 270 | |
259 | 271 | t->tm_year = bcd2bin (Q40_RTC_YEAR); | |
260 | t->tm_year = bcd2bin (Q40_RTC_YEAR); | 272 | t->tm_mon = bcd2bin (Q40_RTC_MNTH)-1; |
261 | t->tm_mon = bcd2bin (Q40_RTC_MNTH)-1; | 273 | t->tm_mday = bcd2bin (Q40_RTC_DATE); |
262 | t->tm_mday = bcd2bin (Q40_RTC_DATE); | 274 | t->tm_hour = bcd2bin (Q40_RTC_HOUR); |
263 | t->tm_hour = bcd2bin (Q40_RTC_HOUR); | 275 | t->tm_min = bcd2bin (Q40_RTC_MINS); |
264 | t->tm_min = bcd2bin (Q40_RTC_MINS); | 276 | t->tm_sec = bcd2bin (Q40_RTC_SECS); |
265 | t->tm_sec = bcd2bin (Q40_RTC_SECS); | 277 | |
266 | 278 | Q40_RTC_CTRL &= ~(Q40_RTC_READ); | |
267 | Q40_RTC_CTRL &= ~(Q40_RTC_READ); | 279 | |
268 | 280 | if (t->tm_year < 70) | |
269 | if (t->tm_year < 70) | 281 | t->tm_year += 100; |
270 | t->tm_year += 100; | 282 | t->tm_wday = bcd2bin(Q40_RTC_DOW)-1; |
271 | t->tm_wday = bcd2bin(Q40_RTC_DOW)-1; | ||
272 | |||
273 | } | 283 | } |
274 | 284 | ||
275 | return 0; | 285 | return 0; |
@@ -285,29 +295,25 @@ unsigned int q40_get_ss(void) | |||
285 | * clock is out by > 30 minutes. Logic lifted from atari code. | 295 | * clock is out by > 30 minutes. Logic lifted from atari code. |
286 | */ | 296 | */ |
287 | 297 | ||
288 | int q40_set_clock_mmss (unsigned long nowtime) | 298 | int q40_set_clock_mmss(unsigned long nowtime) |
289 | { | 299 | { |
290 | int retval = 0; | 300 | int retval = 0; |
291 | short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; | 301 | short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; |
292 | 302 | ||
293 | int rtc_minutes; | 303 | int rtc_minutes; |
294 | 304 | ||
305 | rtc_minutes = bcd2bin(Q40_RTC_MINS); | ||
295 | 306 | ||
296 | rtc_minutes = bcd2bin (Q40_RTC_MINS); | 307 | if ((rtc_minutes < real_minutes ? |
297 | 308 | real_minutes - rtc_minutes : | |
298 | if ((rtc_minutes < real_minutes | 309 | rtc_minutes - real_minutes) < 30) { |
299 | ? real_minutes - rtc_minutes | 310 | Q40_RTC_CTRL |= Q40_RTC_WRITE; |
300 | : rtc_minutes - real_minutes) < 30) | ||
301 | { | ||
302 | Q40_RTC_CTRL |= Q40_RTC_WRITE; | ||
303 | Q40_RTC_MINS = bin2bcd(real_minutes); | 311 | Q40_RTC_MINS = bin2bcd(real_minutes); |
304 | Q40_RTC_SECS = bin2bcd(real_seconds); | 312 | Q40_RTC_SECS = bin2bcd(real_seconds); |
305 | Q40_RTC_CTRL &= ~(Q40_RTC_WRITE); | 313 | Q40_RTC_CTRL &= ~(Q40_RTC_WRITE); |
306 | } | 314 | } else |
307 | else | ||
308 | retval = -1; | 315 | retval = -1; |
309 | 316 | ||
310 | |||
311 | return retval; | 317 | return retval; |
312 | } | 318 | } |
313 | 319 | ||
@@ -318,21 +324,23 @@ int q40_set_clock_mmss (unsigned long nowtime) | |||
318 | 324 | ||
319 | static int q40_get_rtc_pll(struct rtc_pll_info *pll) | 325 | static int q40_get_rtc_pll(struct rtc_pll_info *pll) |
320 | { | 326 | { |
321 | int tmp=Q40_RTC_CTRL; | 327 | int tmp = Q40_RTC_CTRL; |
328 | |||
322 | pll->pll_value = tmp & Q40_RTC_PLL_MASK; | 329 | pll->pll_value = tmp & Q40_RTC_PLL_MASK; |
323 | if (tmp & Q40_RTC_PLL_SIGN) | 330 | if (tmp & Q40_RTC_PLL_SIGN) |
324 | pll->pll_value = -pll->pll_value; | 331 | pll->pll_value = -pll->pll_value; |
325 | pll->pll_max=31; | 332 | pll->pll_max = 31; |
326 | pll->pll_min=-31; | 333 | pll->pll_min = -31; |
327 | pll->pll_posmult=512; | 334 | pll->pll_posmult = 512; |
328 | pll->pll_negmult=256; | 335 | pll->pll_negmult = 256; |
329 | pll->pll_clock=125829120; | 336 | pll->pll_clock = 125829120; |
337 | |||
330 | return 0; | 338 | return 0; |
331 | } | 339 | } |
332 | 340 | ||
333 | static int q40_set_rtc_pll(struct rtc_pll_info *pll) | 341 | static int q40_set_rtc_pll(struct rtc_pll_info *pll) |
334 | { | 342 | { |
335 | if (!pll->pll_ctrl){ | 343 | if (!pll->pll_ctrl) { |
336 | /* the docs are a bit unclear so I am doublesetting */ | 344 | /* the docs are a bit unclear so I am doublesetting */ |
337 | /* RTC_WRITE here ... */ | 345 | /* RTC_WRITE here ... */ |
338 | int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) | | 346 | int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) | |