]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/openslug-kernel-2.6.9/nslu2-io.c
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / openslug-kernel-2.6.9 / nslu2-io.c
1 //=============================================================================
2 //
3 // n2-io.c version 0.1.7
4 // Author: Karen Spearel <kas11 at tampabay.rr.com>
5 // please report problems/bugs directly to the address above
6 //
7 // Boilerplate to be added "real soon now"...it is and has always been GPL'ed per
8 // MODULE_LICENSE but is offered without warrantee of any sort..use at your own risk
9 //
10 // NOTE: THIS IS INCOMPLETE.  INCLUDED ONLY TO KEEP FROM BREAKING THE BUILD,
11 // IT BEEPS AND SENDS A MESSAGE TO /proc/poweroff.  EVENTUALLY IT
12 // WILL TALK TO THE n2_pbd DAEMON.  EVENTUALLY THE LED DRIVER
13 // WILL TALK TO SOME USERLAND APP BUT ***NOT*** SET_LEDS.
14 // 
15 //=============================================================================
16 //      GPIO            Function        State
17 //      0               Red LED         Status          
18 //      1               Green LED       Ready = 1
19 //      2               Disk 2 LED      On = 0
20 //      3               Disk 1 LED      On = 0
21 //      4               Buzzer
22 //      5               Power Button    Pressed = 1
23 //      8               Power Down      Output = 1 powers down N2
24 //      12              Reset           Pressed = 0
25 //=============================================================================
26 // this driver is N2 specific and is purposely designed to do the minimum 
27 // necessary to provide the necessary services given the limited memory resources
28 // of the N2.  As OpenN2 develops, addition features will be added as
29 // suggested by the community.
30 //
31 //=============================================================================
32
33 #include <linux/config.h>
34 #include <linux/version.h>
35 #include <linux/module.h>
36 #include <linux/utsname.h>
37 #include <linux/kernel.h>
38 #include <linux/major.h>
39 #include <linux/string.h>
40 #include <linux/proc_fs.h>
41 #include <linux/slab.h>
42 #include <linux/init.h>
43 #include <linux/errno.h>
44 #include <linux/fs.h>
45 #include <linux/miscdevice.h>
46 #include <linux/device.h>
47 #include <linux/interrupt.h>
48 #include <linux/moduleparam.h>
49 #include <linux/timer.h>
50
51 #include <asm/system.h>
52 #include <asm/uaccess.h>
53 #include <asm/hardware.h>
54 #include <asm-arm/irq.h>
55 #include <asm-arm/delay.h>
56 #include <asm-arm/signal.h>
57
58
59 #define VERSION                 "0.1.7"
60
61 #define N2RB_MAJOR              60
62 #define N2PB_MAJOR              61
63 #define N2BZ_MAJOR              62
64 #define N2LM_MAJOR              126
65
66 #define N2PB_IRQ                22              //gpio5
67 #define N2RB_IRQ                29              //gpio12
68
69 #define N2_BEEP_DUR_LONG        2000
70 #define N2_BEEP_DUR_MED         400
71 #define N2_BEEP_DUR_SHORT       100
72 #define N2_BEEP_PITCH_HIGH      250
73 #define N2_BEEP_PITCH_MED       500
74 #define N2_BEEP_PITCH_LOW       1000
75 #define N2_LONG_DELAY           30000
76
77 #define N2_BZ_GPIO              4
78 #define N2_PB_GPIO              5
79 #define N2_PO_GPIO              8               //power off
80 #define N2_RB_GPIO              12
81
82 #define GPIO_BZ_BM              0x0010  //b0000 0000 0001 0000
83 #define GPIO_PB_BM              0x0020  //b0000 0000 0010 0000
84 #define GPIO_PO_BM              0x0100  //b0000 0001 0000 0000
85 #define GPIO_RB_BM              0x1000  //b0001 0000 0000 0000
86
87 #define NOERR                   0
88
89 #define RB_DELAY                50
90 #define PB_DELAY                20
91
92 #define PWR_OFF_STR             "poweroff"
93
94
95 // ioctls -- 'M" is used for sound cards...we don't got one so it seems safe
96
97 #define N2BZ_BEEP_STOP          _IO('M',0)       //stop multi-beep at end of audible
98 #define N2BZ_BEEP               _IO('M',1)       //one beep at current defaults
99 #define N2BZ_BEEPS              _IOW('M',3,long) //param beeps at current defaults
100 #define N2BZ_TONESET            _IOW('M',4,long) //set tone: range is high=250 to low=2000
101 #define N2BZ_ONTIME             _IOW('M',5,long) //ontime for multi-beeps in jiffies
102 #define N2BZ_SILENTTIME         _IOW('M',6,long) //offtime for multi-beeps in jiffies
103 #define N2BZ_REPEATCNT          _IOW('M',7,long) //number of repeats for multi-beeps 0 = forever
104 #define N2BZ_COMBINED           _IOW('M',8,long) //combine all params in a long
105
106 #define N2LM_OFF                _IOW('M',32,long)
107 #define N2LM_ON                 _IOW('M',33,long)
108 #define N2LM_BLINK              _IOW('M',34,long)
109 #define N2LM_ALT                _IOW('M',35,long)
110 #define N2LM_ALL_ON             _IO('M',36)
111 #define N2LM_ALL_OFF            _IO('M',37)
112
113 #define PHYS_LEDS               4
114 #define BLINK_DELAY             25
115
116 //  OR Masks to turn these LEDs ON
117
118 #define RS_RED_ON       0x00000001      //0b0000 0000 0000 0010
119 #define RS_GRN_ON       0x00000002      //0b0000 0000 0000 0001
120 #define RS_YEL_ON       0x00000003      //0b0000 0000 0000 0011
121
122 // AND Masks to turn these LEDs OFF
123
124 #define RS_RED_OFF      0xfffffffe      //0b1111 1111 1111 1101
125 #define RS_GRN_OFF      0xfffffffd      //0b1111 1111 1111 1110
126 #define RS_YEL_OFF      0xfffffffc      //0b1111 1111 1111 1100
127
128 // AND Masks to turn these LEDs ON
129
130 #define DISK1_ON        0xfffffff7      //0b1111 1111 1111 0111
131 #define DISK2_ON        0xfffffffb      //0b1111 1111 1111 1011
132
133 // Or Masks to turn these LEDs OFF
134
135 #define DISK1_OFF       0x00000008      //0b0000 0000 0000 1000
136 #define DISK2_OFF       0x00000004      //0b0000 0000 0000 0100 
137
138 // EOR masks for toggling LEDs on/off
139
140 #define RS_RG_ALT       0x00000003      //eor mask to toggle rs rg bits
141 #define RS_GRN_TGL      0x00000002
142 #define RS_RED_TGL      0x00000001
143 #define DISK1_TGL       0x00000008
144 #define DISK2_TGL       0x00000004
145
146 // The LED names for switches
147
148 #define LED_RS_RED      0
149 #define LED_RS_GRN      1
150 #define LED_DISK1       2
151 #define LED_DISK2       3
152 #define LED_ALL         4
153
154 static unsigned long init_jiffy = 0;                    //jiffies at init time
155 static unsigned long rb_presses = 0;                    //number of reset button presses
156 static unsigned long ontime = 50;
157 static unsigned long offtime = 450;
158 static unsigned long bz_repeatcnt = 10;
159 static unsigned long tone = 1000;
160
161 DECLARE_WAIT_QUEUE_HEAD(n2rb_waitq);
162 DECLARE_WAIT_QUEUE_HEAD(n2pb_waitq);
163
164 static struct timer_list n2lm_rsg_timer;        //rs green 
165 static struct timer_list n2lm_rsr_timer;        //rs red
166 static struct timer_list n2lm_d1_timer;         //drive 1
167 static struct timer_list n2lm_d2_timer;         //drive 2
168 static struct timer_list n2rb_timer;
169 static struct timer_list n2pb_timer;
170 static struct timer_list n2bz_timer;            //beeper
171
172 //==================================================================================================
173 //
174 // Blinking is handled entirely by the 4 timer handlers.  On timeout, the bit in the
175 // GPIO output register is xor'd with a mask corresponding to the selected led which simply
176 // flips that bit.  No record of what any of the other leds is doing is needed.
177 //
178 //==================================================================================================
179 // this blinks rs green or green/yellow if rs red is on
180 static void n2lm_rsg_handler(unsigned long data)
181 {
182         *IXP4XX_GPIO_GPOUTR ^= RS_GRN_TGL;                      //flip the led
183         n2lm_rsg_timer.expires = jiffies + BLINK_DELAY;         //next timeout
184         add_timer(&n2lm_rsg_timer);                             //reinit timer
185         return;
186 }
187
188 // this blinks or alternates rs red green... inited wit green on/red off
189 static void n2lm_rsr_handler(unsigned long data)
190 {
191         *IXP4XX_GPIO_GPOUTR ^= n2lm_rsr_timer.data;
192         n2lm_rsr_timer.expires = jiffies + BLINK_DELAY;
193         add_timer(&n2lm_rsr_timer);
194         return; 
195 }
196 // blinks disk 1
197 static void n2lm_d1_handler(unsigned long data)
198 {
199         *IXP4XX_GPIO_GPOUTR ^= DISK1_TGL;
200         n2lm_d1_timer.expires = jiffies + BLINK_DELAY;
201         add_timer(&n2lm_d1_timer);
202         return;
203 }
204 // blinks disk 2
205 static void n2lm_d2_handler(unsigned long data)
206 {
207         *IXP4XX_GPIO_GPOUTR ^= DISK2_TGL;
208         n2lm_d2_timer.expires = jiffies + BLINK_DELAY;
209         add_timer(&n2lm_d2_timer);
210         return;
211 }
212
213 //==================================================================================================
214
215 static void n2lm_timer_start(unsigned long led)
216 {
217
218         printk(KERN_DEBUG "timer: %ld\n",led);
219
220         switch(led) {
221                 case LED_RS_RED:
222                         n2lm_rsr_timer.expires = jiffies + BLINK_DELAY;
223                         add_timer(&n2lm_rsr_timer);
224                         break;
225
226                 case LED_RS_GRN:
227                         n2lm_rsg_timer.expires = jiffies + BLINK_DELAY;
228                         add_timer(&n2lm_rsg_timer);
229                         break;
230
231                 case LED_DISK1:
232                         n2lm_d1_timer.expires = jiffies + BLINK_DELAY;
233                         add_timer(&n2lm_d1_timer);
234                         break;
235
236                 case LED_DISK2:
237                         n2lm_d2_timer.expires = jiffies + BLINK_DELAY; 
238                         add_timer(&n2lm_d2_timer);
239                         break;
240
241                 default:
242                         break;
243         }
244         return;
245 }
246
247 //==================================================================================================
248
249 static void n2lm_timer_stop(unsigned long led)
250 {
251         switch (led) {
252                 case LED_RS_RED:
253                         del_timer(&n2lm_rsr_timer);
254                         break;
255                 case LED_RS_GRN:
256                         del_timer(&n2lm_rsg_timer);
257                         break;
258                 case LED_DISK1:
259                         del_timer(&n2lm_d1_timer);
260                         break;
261                 case LED_DISK2: 
262                         del_timer(&n2lm_d2_timer);
263                         break;
264                 default:
265                         break;
266         }
267         return;
268 }
269
270 //--------------------------------------------------------------------------------------------------
271
272 static void n2lm_timer_stop_all(void)
273 {
274         del_timer(&n2lm_rsg_timer);
275         del_timer(&n2lm_rsr_timer);
276         del_timer(&n2lm_d1_timer); 
277         del_timer(&n2lm_d2_timer);
278         return;
279 }
280 //--------------------------------------------------------------------------------------------------
281
282 static void n2lm_ledon(unsigned long led)
283 {
284
285         printk(KERN_DEBUG "ledon: %ld\n", led);
286
287         switch (led) {
288                 case LED_RS_RED:        
289                         *IXP4XX_GPIO_GPOUTR |= RS_RED_ON;       //1
290                         return;
291                 case LED_RS_GRN:
292                         *IXP4XX_GPIO_GPOUTR |= RS_GRN_ON;       //2
293                         return;
294                 case LED_DISK1:
295                         *IXP4XX_GPIO_GPOUTR &= DISK1_ON;        //0xfffffffb
296                         return;
297                 case LED_DISK2: 
298                         *IXP4XX_GPIO_GPOUTR &= DISK2_ON;        //0xfffffff7
299                         return;
300                 case LED_ALL:                                   //all green
301                         *IXP4XX_GPIO_GPOUTR |= RS_GRN_ON;
302                         *IXP4XX_GPIO_GPOUTR &= (DISK1_ON & DISK2_ON);
303                         return; 
304         }
305 }
306
307 //--------------------------------------------------------------------------------------------------
308
309 static void n2lm_ledoff(unsigned long led)
310 {
311
312         switch (led) {
313                 case LED_RS_RED:        
314                         *IXP4XX_GPIO_GPOUTR &= RS_RED_OFF;      //0xffffffffe
315                         return;
316                 case LED_RS_GRN:
317                         *IXP4XX_GPIO_GPOUTR &= RS_GRN_OFF;      //0xfffffffd
318                         return;
319                 case LED_DISK1:
320                         *IXP4XX_GPIO_GPOUTR |= DISK1_OFF;       //0x00000004
321                         return;
322                 case LED_DISK2: 
323                         *IXP4XX_GPIO_GPOUTR |= DISK2_OFF;       //0x00000008
324                         return;
325                 case LED_ALL:
326                         *IXP4XX_GPIO_GPOUTR &= (RS_GRN_OFF & RS_RED_OFF);
327                         *IXP4XX_GPIO_GPOUTR |= (DISK1_OFF | DISK2_OFF);
328         }
329 }
330
331 //==================================================================================================
332
333 static int n2lm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long led)
334 {
335
336         printk(KERN_DEBUG "cmd=%d, led=%ld\n", cmd, led);
337         
338         if (led < 0 || led >= PHYS_LEDS)
339                 return -EINVAL;
340
341         switch (cmd ) {
342                 case N2LM_ON:
343                         n2lm_timer_stop(led);
344                         n2lm_ledon(led);
345                         break;
346                         
347                 case N2LM_OFF:
348                         n2lm_timer_stop(led);
349                         n2lm_ledoff(led);
350                         break;
351                         
352                 case N2LM_BLINK:
353                         n2lm_ledon(led);
354                         if (led == LED_RS_RED)
355                                 n2lm_rsr_timer.data = RS_RED_TGL;
356                         if (led == LED_RS_GRN)
357                                 n2lm_rsr_timer.data = RS_GRN_TGL;
358                         n2lm_timer_start(led);
359                         break;
360
361                 case N2LM_ALT:
362                         if (led == LED_RS_RED)
363                         {
364                                 n2lm_ledon(LED_RS_GRN);
365                                 n2lm_ledoff(LED_RS_RED);
366                                 n2lm_rsr_timer.data = RS_RG_ALT;
367                                 n2lm_timer_start(LED_RS_RED);
368                                 break;
369                         } else
370                                 return -EINVAL;
371                 
372                 case N2LM_ALL_ON:
373                         n2lm_timer_stop_all();
374                         n2lm_ledon(LED_ALL);
375                         break;
376                 
377                 case N2LM_ALL_OFF:
378                         n2lm_timer_stop_all();
379                         n2lm_ledoff(LED_ALL);
380                         break;
381                 
382                 default:
383                         return -EINVAL;
384         }
385
386         return NOERR;
387 }
388
389 static struct file_operations n2lm_fops = {
390         .owner          = THIS_MODULE,
391         .ioctl          = n2lm_ioctl,
392 };
393 //==================================================================================================
394 // We can't do anything fancy here since the system tick rate is far below that required to
395 // generate a desirable tone.  Therefore we haven't much choice but to use a busy loop until
396 // I get up to speed on the timers.  The saving grace is that for the normal uses, nothing 
397 // important should be haprepening. 
398 //==================================================================================================
399
400 static void n2_buzz(int tone_delay, int duration)
401 {
402         int i;
403
404         *IXP4XX_GPIO_GPOER &= ~GPIO_BZ_BM;
405                 
406         for (i = 1; i < duration; i++) {
407                 *IXP4XX_GPIO_GPOUTR &= ~GPIO_BZ_BM;
408                 udelay(tone_delay);
409                 *IXP4XX_GPIO_GPOUTR |= GPIO_BZ_BM;
410                 udelay(tone_delay);
411         }
412         *IXP4XX_GPIO_GPOER |= GPIO_BZ_BM;
413
414         return;
415 }
416 //=================================================================================================
417
418 // this handles the buzzer duty cycle
419 static void n2bz_handler(unsigned long data)
420 {
421         if (--bz_repeatcnt > 0) {                       //if just one beep left to do
422                 n2bz_timer.expires = jiffies + ontime + offtime;        //next timeout
423                 add_timer(&n2bz_timer);                                 //reinit timer
424         }
425         n2_buzz(tone/2, ontime);
426         printk(KERN_DEBUG "Count = %d\tOntime = %d\n", bz_repeatcnt, ontime);
427         return;
428 }
429
430 //==================================================================================================
431
432 static int n2bz_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param)
433 {
434         switch (cmd) {
435                 case N2BZ_BEEP:
436                         n2_buzz(tone/2, ontime);
437                         break;
438         
439                 case N2BZ_BEEP_STOP:
440                         del_timer(&n2bz_timer);
441                         break;
442
443                 case N2BZ_BEEPS:
444                         if (param == 0)
445                                 bz_repeatcnt = 0xffffffff;
446                         else
447                                 bz_repeatcnt = param;
448                         n2bz_handler(0);
449                         break;
450         
451                 case N2BZ_TONESET:
452                         if (param >= 250 && param <= 2000)
453                                 tone = param;
454                         break;
455
456                 case N2BZ_ONTIME:
457                         if (param > 4 && param < 201)
458                                 ontime = param;
459                         break;
460
461                 case N2BZ_SILENTTIME:
462                         if (param > ontime)                     //enforce a reasonable duty cycle
463                                 offtime = param;
464                         else
465                                 offtime = ontime;
466                         break;
467
468                 case N2BZ_REPEATCNT:
469                         if (param == 0)
470                                 bz_repeatcnt = 0xffffffff;
471                         else
472                                 bz_repeatcnt = param;
473                         break;
474
475                 case N2BZ_COMBINED:
476                         bz_repeatcnt =  (param & 0xF0000000) >> 28;     //repeat 1 - 16
477                         ontime =        (param & 0x0FF00000) >> 20;     //ontime 1 - 256 jiffies
478                         offtime =       (param & 0x000FFF00) >> 8;      //offtime 1 - 4095 jiffies
479                         tone =          (param & 0x000000FF) << 4;      //tone (1 - 255) * 16
480                         break;
481
482                 default:
483                         break;
484         }
485         return NOERR;
486 }
487
488 static struct file_operations n2bz_fops = {
489         .owner          = THIS_MODULE,
490         .ioctl          = n2bz_ioctl,
491 };
492
493 //==================================================================================================
494                 
495 static irqreturn_t n2pb_handler (int irq, void *dev_id, struct pt_regs *regs)
496 {
497         void *ret;
498         
499         wake_up(&n2pb_waitq);   
500         remove_proc_entry(PWR_OFF_STR, NULL);           //no parent     
501         n2_buzz(N2_BEEP_PITCH_MED, N2_BEEP_DUR_MED);
502         ret = create_proc_entry(PWR_OFF_STR, 0, NULL);
503         printk(KERN_DEBUG "cpe ret = %p\n", ret);
504
505 // WARNING: This is RUDE...it unconditionally pulls the power plug.
506 // Your data will be at risk...since this is just a test system
507 // I am leaving it enabled...eventually userland needs to get the
508 // message, do an orderly shutdown and use an ioctl or something in
509 // /proc/powerdowm to actually have us pull the plug.
510
511         *IXP4XX_GPIO_GPOER &= ~GPIO_PO_BM;      // enable the pwr cntl gpio
512         *IXP4XX_GPIO_GPOUTR |= GPIO_PO_BM;      // do the deed
513
514         return IRQ_HANDLED;
515 }
516
517 //==================================================================================================
518 //
519 //static void do_rb_timeout(unsigned long data)
520 //{
521 //      int i;
522 //
523 //      for (i = 0; i < rb_presses; i++)
524 //              n2_buzz(N2_BEEP_PITCH_MED,N2_BEEP_DUR_SHORT);
525 //      return;
526 //}
527 //
528 //==================================================================================================
529 // does nothing -- waiting for userland to define
530 // This thing is sorta braindead...edge triggered IRQs aren't available in the drivers yet...so
531 // we hang in a loop until the button is no longer pressed
532
533 struct testr {
534         int     ctl;
535         long    param;
536 };
537
538 static irqreturn_t n2rb_handler (int irq, void *dev_id, struct pt_regs *regs)
539 {
540
541         static struct testr test[] = {
542                                  N2LM_ALL_OFF,0,
543                                  N2LM_ON,0,
544                                  N2LM_OFF,0,
545                                  N2LM_ON,1,
546                                  N2LM_ALL_OFF,1, 
547                                  N2LM_ON,2,
548                                  N2LM_OFF,2,
549                                  N2LM_ON,3,
550                                  N2LM_OFF,3,
551                                  N2LM_BLINK,0,
552                                  N2LM_OFF,0,
553                                  N2LM_BLINK,1,
554                                  N2LM_OFF,1,
555                                  N2LM_BLINK,2,
556                                  N2LM_OFF,2,
557                                  N2LM_BLINK,3,
558                                  N2LM_OFF,3,
559                                  N2LM_ALL_OFF,0,
560                                  N2LM_ALT,1,
561                                  N2LM_OFF,1,
562                                  N2LM_ALL_ON,0
563         };
564
565         printk("Reset Entry IRQ =%d Presses = %d Jiffies = %08lx\tIO = %x\tIOW = %x\n", irq, rb_presses, jiffies, (int)_IO('M',rb_presses), (int)_IOW('M',rb_presses,long));
566
567         wake_up(&n2rb_waitq);   
568         while ((*IXP4XX_GPIO_GPINR & GPIO_RB_BM) == 0)
569                 ;                                       //wait for button release
570
571         if (rb_presses > 20) 
572                 rb_presses = 0;
573         tone = (rb_presses * 50) + 200;
574         ontime = (rb_presses*10) + 100;
575         offtime = 500 - (rb_presses*20);
576         printk("Ontime = %d\tOfftime = %d\tTone = %d\n",ontime,offtime,tone);
577         rb_presses++;
578
579         n2bz_ioctl(NULL,NULL, N2BZ_BEEPS, rb_presses);  
580         n2lm_ioctl(NULL,NULL, test[rb_presses].ctl, test[rb_presses].param);
581 //      if (rb_presses == 0) {
582 //              init_jiffy = jiffies;
583 //              init_timer (&n2rb_timer);
584 //              n2rb_timer.function = do_rb_timeout;
585 //      };
586 //
587 //      if (rb_presses == 8)
588 //              rb_presses = 0;
589 //      if (rb_presses & 1)
590 //              n2lm_ledon(test[rb_presses]);
591 //      else
592 //              n2lm_ledoff(test[rb_presses]);
593 //      
594 //      n2rb_timer.expires = (jiffies + RB_DELAY);
595 //      add_timer (&n2rb_timer);
596 //      if (rb_presses < 5) {
597 //              if (rb_presses > 0)
598 //                      n2lm_ledoff(rb_presses);
599 //              n2lm_ledon(++rb_presses);
600 //              n2lm_timer_start(rb_presses);
601 //      };
602
603         printk(KERN_DEBUG "Reset Exit IRQ=%d Presses= %d Jiffies= %08lx\n", irq, rb_presses, jiffies);
604         return IRQ_HANDLED;
605
606 }
607
608 //==================================================================================================
609 //  What to do here is majorly undetermined...
610
611 static int n2rb_read (struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
612 {
613         printk(KERN_DEBUG "Reset Button Wait\n");
614         interruptible_sleep_on(&n2rb_waitq);
615         return copy_to_user(buffer, "reset", 5) ? -EFAULT : 5;
616
617 }
618
619 //==================================================================================================
620 //  What to do here is majorly undetermined...
621
622 static int n2pb_read (struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
623 {
624         printk(KERN_DEBUG "Power Button Wait\n");
625         interruptible_sleep_on(&n2pb_waitq);
626         return copy_to_user(buffer, "poweroff", 8) ? -EFAULT : 8;
627
628 }
629
630 //--------------------------------------------------------------------------------------------------
631
632 static struct file_operations n2rb_fops = {
633         .owner          = THIS_MODULE,
634         .read           = n2rb_read,
635 };
636
637 //--------------------------------------------------------------------------------------------------
638
639 static struct file_operations n2pb_fops = {
640         .owner          = THIS_MODULE,
641         .read           = n2pb_read,
642 };
643
644 //==================================================================================================
645
646 static void n2iom_initarch(void)
647 {
648         printk(KERN_DEBUG "setup_interrupts - jiffies=%ld init_jiffy=%ld\n", jiffies, init_jiffy);
649
650         *IXP4XX_GPIO_GPISR = 0x20400000;        // read the 2 irqs to clr
651         gpio_line_config(N2_RB_GPIO, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
652         gpio_line_isr_clear(N2_RB_GPIO);
653         gpio_line_config(N2_PB_GPIO, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_HIGH);
654         gpio_line_isr_clear(N2_PB_GPIO);
655
656         init_timer(&n2lm_rsg_timer);
657         init_timer(&n2lm_rsr_timer);
658         init_timer(&n2lm_d1_timer);
659         init_timer(&n2lm_d2_timer);
660 //      init_timer(&n2rb_timer);
661 //      init_timer(&n2pb_timer);
662         init_timer(&n2bz_timer);
663         n2lm_rsr_timer.function = n2lm_rsr_handler;
664         n2lm_rsg_timer.function = n2lm_rsg_handler;
665         n2lm_d2_timer.function = n2lm_d2_handler;
666         n2lm_d1_timer.function = n2lm_d1_handler;
667         n2bz_timer.function = n2bz_handler;
668         n2lm_rsr_timer.data = n2lm_rsg_timer.data = n2lm_d1_timer.data = n2lm_d2_timer.data = n2bz_timer.data = 0;
669
670         *IXP4XX_GPIO_GPOER &= 0xfffffff0;       //enable gpio 0-3
671         *IXP4XX_GPIO_GPOUTR |= 0x00000003;      //turn off the leds
672         *IXP4XX_GPIO_GPOUTR &= 0xfffffffc;
673         n2lm_ledon(LED_ALL);
674         n2_buzz(N2_BEEP_PITCH_MED, N2_BEEP_DUR_SHORT);
675         n2lm_ledoff(LED_ALL);
676 // Default the Ready/Status to Red during kernel boot, Turn Green at the end of sysvinit
677         n2lm_ledon(LED_RS_RED);
678
679         return;
680 }
681
682 //==================================================================================================
683
684 static int __init n2iom_init(void)
685 {
686         printk(KERN_INFO "OpenN2 Misc I/O Driver Version %s\n", VERSION);
687         
688         init_jiffy = jiffies;
689         printk(KERN_DEBUG "init_jiffy=%ld\n",init_jiffy);
690         n2iom_initarch();
691
692         if (register_chrdev(N2RB_MAJOR, "n2_rbm", &n2pb_fops) < NOERR) {
693                 printk(KERN_DEBUG "Reset Button Major %d not available\n", N2RB_MAJOR);
694                 return -EBUSY;
695         }
696         if (register_chrdev(N2PB_MAJOR, "n2_pbm", &n2rb_fops) < NOERR) {
697                 printk(KERN_DEBUG "Power Button Major %d not available\n", N2PB_MAJOR);
698                 return -EBUSY;
699         }
700         if (register_chrdev(N2LM_MAJOR, "n2_ledm", &n2lm_fops) < NOERR) {
701                 printk(KERN_DEBUG "Led Manager Major %d not available\n", N2LM_MAJOR);
702                 return -EBUSY;
703         }
704         if (register_chrdev(N2BZ_MAJOR, "n2_bzm", &n2bz_fops) < NOERR) {
705                 printk(KERN_DEBUG "Buzzer Major %d not available\n", N2BZ_MAJOR);
706                 return -EBUSY;
707         }
708
709         if (request_irq(N2RB_IRQ, &n2rb_handler, SA_INTERRUPT, "n2_rb", NULL) < NOERR) {
710                 printk(KERN_DEBUG "Reset Button IRQ %d not available\n", N2RB_IRQ);
711                 return -EIO;
712         }
713         if (request_irq(N2PB_IRQ, &n2pb_handler, SA_INTERRUPT, "n2_pb", NULL) < NOERR) {
714                 printk(KERN_DEBUG "Power Button IRQ %d not available\n", N2PB_IRQ);
715                 return -EIO;    
716         }
717         
718         enable_irq(N2PB_IRQ);
719         enable_irq(N2RB_IRQ);
720         return (NOERR);
721 }
722
723 //==================================================================================================
724
725 static void __exit n2iom_exit(void)
726 {
727         remove_proc_entry(PWR_OFF_STR, NULL);
728         del_timer(&n2rb_timer);
729         free_irq(N2RB_IRQ,NULL);
730         unregister_chrdev(N2PB_MAJOR, "n2pb");
731         del_timer(&n2pb_timer); 
732         free_irq(N2PB_IRQ, NULL);
733         unregister_chrdev(N2RB_MAJOR, "n2rb" );
734         del_timer(&n2lm_rsg_timer);
735         del_timer(&n2lm_rsr_timer);
736         del_timer(&n2lm_d1_timer);
737         del_timer(&n2lm_d2_timer);      
738         unregister_chrdev(N2LM_MAJOR, "n2lm" );
739 }
740
741 module_init (n2iom_init);
742 module_exit (n2iom_exit);
743
744 MODULE_AUTHOR("Karen Spearel <kas11@tampabay.rr.com>");
745 MODULE_DESCRIPTION("OpenN2 Buttons/LEDs IO Driver");
746 MODULE_LICENSE("GPL");
747 static int debug = 7;
748 module_param(debug, int, 0644);
749 MODULE_PARM_DESC(debug, "Debugging enabled = 8");
750