sky2: software rx/tx stats
[linux-2.6] / drivers / char / lcd.c
1 /*
2  * LCD, LED and Button interface for Cobalt
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 1996, 1997 by Andrew Bose
9  *
10  * Linux kernel version history:
11  *       March 2001: Ported from 2.0.34  by Liam Davies
12  *
13  */
14
15 #define RTC_IO_EXTENT   0x10    /*Only really two ports, but... */
16
17 #include <linux/types.h>
18 #include <linux/errno.h>
19 #include <linux/miscdevice.h>
20 #include <linux/slab.h>
21 #include <linux/ioport.h>
22 #include <linux/fcntl.h>
23 #include <linux/mc146818rtc.h>
24 #include <linux/netdevice.h>
25 #include <linux/sched.h>
26 #include <linux/delay.h>
27
28 #include <asm/io.h>
29 #include <asm/uaccess.h>
30 #include <asm/system.h>
31 #include <linux/delay.h>
32
33 #include "lcd.h"
34
35 static DEFINE_SPINLOCK(lcd_lock);
36
37 static int lcd_ioctl(struct inode *inode, struct file *file,
38                      unsigned int cmd, unsigned long arg);
39
40 static unsigned int lcd_present = 1;
41
42 /* used in arch/mips/cobalt/reset.c */
43 int led_state = 0;
44
45 #if defined(CONFIG_TULIP) && 0
46
47 #define MAX_INTERFACES  8
48 static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES];
49 static void *linkcheck_cookies[MAX_INTERFACES];
50
51 int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie)
52 {
53         if (iface_num < 0 ||
54             iface_num >= MAX_INTERFACES ||
55             linkcheck_callbacks[iface_num] != NULL)
56                 return -1;
57         linkcheck_callbacks[iface_num] = (linkcheck_func_t) func;
58         linkcheck_cookies[iface_num] = cookie;
59         return 0;
60 }
61 #endif
62
63 static int lcd_ioctl(struct inode *inode, struct file *file,
64                      unsigned int cmd, unsigned long arg)
65 {
66         struct lcd_display button_display;
67         unsigned long address, a;
68
69         switch (cmd) {
70         case LCD_On:
71                 udelay(150);
72                 BusyCheck();
73                 LCDWriteInst(0x0F);
74                 break;
75
76         case LCD_Off:
77                 udelay(150);
78                 BusyCheck();
79                 LCDWriteInst(0x08);
80                 break;
81
82         case LCD_Reset:
83                 udelay(150);
84                 LCDWriteInst(0x3F);
85                 udelay(150);
86                 LCDWriteInst(0x3F);
87                 udelay(150);
88                 LCDWriteInst(0x3F);
89                 udelay(150);
90                 LCDWriteInst(0x3F);
91                 udelay(150);
92                 LCDWriteInst(0x01);
93                 udelay(150);
94                 LCDWriteInst(0x06);
95                 break;
96
97         case LCD_Clear:
98                 udelay(150);
99                 BusyCheck();
100                 LCDWriteInst(0x01);
101                 break;
102
103         case LCD_Cursor_Left:
104                 udelay(150);
105                 BusyCheck();
106                 LCDWriteInst(0x10);
107                 break;
108
109         case LCD_Cursor_Right:
110                 udelay(150);
111                 BusyCheck();
112                 LCDWriteInst(0x14);
113                 break;
114
115         case LCD_Cursor_Off:
116                 udelay(150);
117                 BusyCheck();
118                 LCDWriteInst(0x0C);
119                 break;
120
121         case LCD_Cursor_On:
122                 udelay(150);
123                 BusyCheck();
124                 LCDWriteInst(0x0F);
125                 break;
126
127         case LCD_Blink_Off:
128                 udelay(150);
129                 BusyCheck();
130                 LCDWriteInst(0x0E);
131                 break;
132
133         case LCD_Get_Cursor_Pos:{
134                         struct lcd_display display;
135
136                         udelay(150);
137                         BusyCheck();
138                         display.cursor_address = (LCDReadInst);
139                         display.cursor_address =
140                             (display.cursor_address & 0x07F);
141                         if (copy_to_user
142                             ((struct lcd_display *) arg, &display,
143                              sizeof(struct lcd_display)))
144                                 return -EFAULT;
145
146                         break;
147                 }
148
149
150         case LCD_Set_Cursor_Pos:{
151                         struct lcd_display display;
152
153                         if (copy_from_user
154                             (&display, (struct lcd_display *) arg,
155                              sizeof(struct lcd_display)))
156                                 return -EFAULT;
157
158                         a = (display.cursor_address | kLCD_Addr);
159
160                         udelay(150);
161                         BusyCheck();
162                         LCDWriteInst(a);
163
164                         break;
165                 }
166
167         case LCD_Get_Cursor:{
168                         struct lcd_display display;
169
170                         udelay(150);
171                         BusyCheck();
172                         display.character = LCDReadData;
173
174                         if (copy_to_user
175                             ((struct lcd_display *) arg, &display,
176                              sizeof(struct lcd_display)))
177                                 return -EFAULT;
178                         udelay(150);
179                         BusyCheck();
180                         LCDWriteInst(0x10);
181
182                         break;
183                 }
184
185         case LCD_Set_Cursor:{
186                         struct lcd_display display;
187
188                         if (copy_from_user
189                             (&display, (struct lcd_display *) arg,
190                              sizeof(struct lcd_display)))
191                                 return -EFAULT;
192
193                         udelay(150);
194                         BusyCheck();
195                         LCDWriteData(display.character);
196                         udelay(150);
197                         BusyCheck();
198                         LCDWriteInst(0x10);
199
200                         break;
201                 }
202
203
204         case LCD_Disp_Left:
205                 udelay(150);
206                 BusyCheck();
207                 LCDWriteInst(0x18);
208                 break;
209
210         case LCD_Disp_Right:
211                 udelay(150);
212                 BusyCheck();
213                 LCDWriteInst(0x1C);
214                 break;
215
216         case LCD_Home:
217                 udelay(150);
218                 BusyCheck();
219                 LCDWriteInst(0x02);
220                 break;
221
222         case LCD_Write:{
223                         struct lcd_display display;
224                         unsigned int index;
225
226
227                         if (copy_from_user
228                             (&display, (struct lcd_display *) arg,
229                              sizeof(struct lcd_display)))
230                                 return -EFAULT;
231
232                         udelay(150);
233                         BusyCheck();
234                         LCDWriteInst(0x80);
235                         udelay(150);
236                         BusyCheck();
237
238                         for (index = 0; index < (display.size1); index++) {
239                                 udelay(150);
240                                 BusyCheck();
241                                 LCDWriteData(display.line1[index]);
242                                 BusyCheck();
243                         }
244
245                         udelay(150);
246                         BusyCheck();
247                         LCDWriteInst(0xC0);
248                         udelay(150);
249                         BusyCheck();
250                         for (index = 0; index < (display.size2); index++) {
251                                 udelay(150);
252                                 BusyCheck();
253                                 LCDWriteData(display.line2[index]);
254                         }
255
256                         break;
257                 }
258
259         case LCD_Read:{
260                         struct lcd_display display;
261
262                         BusyCheck();
263                         for (address = kDD_R00; address <= kDD_R01;
264                              address++) {
265                                 a = (address | kLCD_Addr);
266
267                                 udelay(150);
268                                 BusyCheck();
269                                 LCDWriteInst(a);
270                                 udelay(150);
271                                 BusyCheck();
272                                 display.line1[address] = LCDReadData;
273                         }
274
275                         display.line1[0x27] = '\0';
276
277                         for (address = kDD_R10; address <= kDD_R11;
278                              address++) {
279                                 a = (address | kLCD_Addr);
280
281                                 udelay(150);
282                                 BusyCheck();
283                                 LCDWriteInst(a);
284
285                                 udelay(150);
286                                 BusyCheck();
287                                 display.line2[address - 0x40] =
288                                     LCDReadData;
289                         }
290
291                         display.line2[0x27] = '\0';
292
293                         if (copy_to_user
294                             ((struct lcd_display *) arg, &display,
295                              sizeof(struct lcd_display)))
296                                 return -EFAULT;
297                         break;
298                 }
299
300 //  set all GPIO leds to led_display.leds
301
302         case LED_Set:{
303                         struct lcd_display led_display;
304
305
306                         if (copy_from_user
307                             (&led_display, (struct lcd_display *) arg,
308                              sizeof(struct lcd_display)))
309                                 return -EFAULT;
310
311                         led_state = led_display.leds;
312                         LEDSet(led_state);
313
314                         break;
315                 }
316
317
318 //  set only bit led_display.leds
319
320         case LED_Bit_Set:{
321                         unsigned int i;
322                         int bit = 1;
323                         struct lcd_display led_display;
324
325
326                         if (copy_from_user
327                             (&led_display, (struct lcd_display *) arg,
328                              sizeof(struct lcd_display)))
329                                 return -EFAULT;
330
331                         for (i = 0; i < (int) led_display.leds; i++) {
332                                 bit = 2 * bit;
333                         }
334
335                         led_state = led_state | bit;
336                         LEDSet(led_state);
337                         break;
338                 }
339
340 //  clear only bit led_display.leds
341
342         case LED_Bit_Clear:{
343                         unsigned int i;
344                         int bit = 1;
345                         struct lcd_display led_display;
346
347
348                         if (copy_from_user
349                             (&led_display, (struct lcd_display *) arg,
350                              sizeof(struct lcd_display)))
351                                 return -EFAULT;
352
353                         for (i = 0; i < (int) led_display.leds; i++) {
354                                 bit = 2 * bit;
355                         }
356
357                         led_state = led_state & ~bit;
358                         LEDSet(led_state);
359                         break;
360                 }
361
362
363         case BUTTON_Read:{
364                         button_display.buttons = GPIRead;
365                         if (copy_to_user
366                             ((struct lcd_display *) arg, &button_display,
367                              sizeof(struct lcd_display)))
368                                 return -EFAULT;
369                         break;
370                 }
371
372         case LINK_Check:{
373                         button_display.buttons =
374                             *((volatile unsigned long *) (0xB0100060));
375                         if (copy_to_user
376                             ((struct lcd_display *) arg, &button_display,
377                              sizeof(struct lcd_display)))
378                                 return -EFAULT;
379                         break;
380                 }
381
382         case LINK_Check_2:{
383                         int iface_num;
384
385                         /* panel-utils should pass in the desired interface status is wanted for
386                          * in "buttons" of the structure.  We will set this to non-zero if the
387                          * link is in fact up for the requested interface.  --DaveM
388                          */
389                         if (copy_from_user
390                             (&button_display, (struct lcd_display *) arg,
391                              sizeof(button_display)))
392                                 return -EFAULT;
393                         iface_num = button_display.buttons;
394 #if defined(CONFIG_TULIP) && 0
395                         if (iface_num >= 0 &&
396                             iface_num < MAX_INTERFACES &&
397                             linkcheck_callbacks[iface_num] != NULL) {
398                                 button_display.buttons =
399                                     linkcheck_callbacks[iface_num]
400                                     (linkcheck_cookies[iface_num]);
401                         } else
402 #endif
403                                 button_display.buttons = 0;
404
405                         if (__copy_to_user
406                             ((struct lcd_display *) arg, &button_display,
407                              sizeof(struct lcd_display)))
408                                 return -EFAULT;
409                         break;
410                 }
411
412 //  Erase the flash
413
414         case FLASH_Erase:{
415
416                         int ctr = 0;
417
418                         if ( !capable(CAP_SYS_ADMIN) ) return -EPERM;
419
420                         pr_info(LCD "Erasing Flash\n");
421
422                         // Chip Erase Sequence
423                         WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
424                         WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
425                         WRITE_FLASH(kFlash_Addr1, kFlash_Erase3);
426                         WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
427                         WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
428                         WRITE_FLASH(kFlash_Addr1, kFlash_Erase6);
429
430                         while ((!dqpoll(0x00000000, 0xFF))
431                                && (!timeout(0x00000000))) {
432                                 ctr++;
433                         }
434
435                         if (READ_FLASH(0x07FFF0) == 0xFF) {
436                                 pr_info(LCD "Erase Successful\n");
437                         } else if (timeout) {
438                                 pr_info(LCD "Erase Timed Out\n");
439                         }
440
441                         break;
442                 }
443
444 // burn the flash
445
446         case FLASH_Burn:{
447
448                         volatile unsigned long burn_addr;
449                         unsigned long flags;
450                         unsigned int i, index;
451                         unsigned char *rom;
452
453
454                         struct lcd_display display;
455
456                         if ( !capable(CAP_SYS_ADMIN) ) return -EPERM;
457
458                         if (copy_from_user
459                             (&display, (struct lcd_display *) arg,
460                              sizeof(struct lcd_display)))
461                                 return -EFAULT;
462                         rom = kmalloc((128), GFP_ATOMIC);
463                         if (rom == NULL) {
464                                 printk(KERN_ERR LCD "kmalloc() failed in %s\n",
465                                                 __FUNCTION__);
466                                 return -ENOMEM;
467                         }
468
469                         pr_info(LCD "Starting Flash burn\n");
470                         for (i = 0; i < FLASH_SIZE; i = i + 128) {
471
472                                 if (copy_from_user
473                                     (rom, display.RomImage + i, 128)) {
474                                         kfree(rom);
475                                         return -EFAULT;
476                                 }
477                                 burn_addr = kFlashBase + i;
478                                 spin_lock_irqsave(&lcd_lock, flags);
479                                 for (index = 0; index < (128); index++) {
480
481                                         WRITE_FLASH(kFlash_Addr1,
482                                                     kFlash_Data1);
483                                         WRITE_FLASH(kFlash_Addr2,
484                                                     kFlash_Data2);
485                                         WRITE_FLASH(kFlash_Addr1,
486                                                     kFlash_Prog);
487                                         *((volatile unsigned char *)burn_addr) =
488                                           (volatile unsigned char) rom[index];
489
490                                         while ((!dqpoll (burn_addr,
491                                                 (volatile unsigned char)
492                                                 rom[index])) &&
493                                                 (!timeout(burn_addr))) { }
494                                         burn_addr++;
495                                 }
496                                 spin_unlock_irqrestore(&lcd_lock, flags);
497                                 if (* ((volatile unsigned char *)
498                                         (burn_addr - 1)) ==
499                                         (volatile unsigned char)
500                                         rom[index - 1]) {
501                                 } else if (timeout) {
502                                         pr_info(LCD "Flash burn timed out\n");
503                                 }
504
505
506                         }
507                         kfree(rom);
508
509                         pr_info(LCD "Flash successfully burned\n");
510
511                         break;
512                 }
513
514 //  read the flash all at once
515
516         case FLASH_Read:{
517
518                         unsigned char *user_bytes;
519                         volatile unsigned long read_addr;
520                         unsigned int i;
521
522                         user_bytes =
523                             &(((struct lcd_display *) arg)->RomImage[0]);
524
525                         if (!access_ok
526                             (VERIFY_WRITE, user_bytes, FLASH_SIZE))
527                                 return -EFAULT;
528
529                         pr_info(LCD "Reading Flash");
530                         for (i = 0; i < FLASH_SIZE; i++) {
531                                 unsigned char tmp_byte;
532                                 read_addr = kFlashBase + i;
533                                 tmp_byte =
534                                     *((volatile unsigned char *)
535                                       read_addr);
536                                 if (__put_user(tmp_byte, &user_bytes[i]))
537                                         return -EFAULT;
538                         }
539
540
541                         break;
542                 }
543
544         default:
545                 return -EINVAL;
546
547         }
548
549         return 0;
550
551 }
552
553 static int lcd_open(struct inode *inode, struct file *file)
554 {
555         if (!lcd_present)
556                 return -ENXIO;
557         else
558                 return 0;
559 }
560
561 /* Only RESET or NEXT counts as button pressed */
562
563 static inline int button_pressed(void)
564 {
565         unsigned long buttons = GPIRead;
566
567         if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B)
568             || (buttons == BUTTON_Reset_B))
569                 return buttons;
570         return 0;
571 }
572
573 /* LED daemon sits on this and we wake him up once a key is pressed. */
574
575 static int lcd_waiters = 0;
576
577 static ssize_t lcd_read(struct file *file, char *buf,
578                      size_t count, loff_t *ofs)
579 {
580         long buttons_now;
581
582         if (lcd_waiters > 0)
583                 return -EINVAL;
584
585         lcd_waiters++;
586         while (((buttons_now = (long) button_pressed()) == 0) &&
587                !(signal_pending(current))) {
588                 msleep_interruptible(2000);
589         }
590         lcd_waiters--;
591
592         if (signal_pending(current))
593                 return -ERESTARTSYS;
594         return buttons_now;
595 }
596
597 /*
598  *      The various file operations we support.
599  */
600
601 static const struct file_operations lcd_fops = {
602         .read = lcd_read,
603         .ioctl = lcd_ioctl,
604         .open = lcd_open,
605 };
606
607 static struct miscdevice lcd_dev = {
608         MISC_DYNAMIC_MINOR,
609         "lcd",
610         &lcd_fops
611 };
612
613 static int lcd_init(void)
614 {
615         int ret;
616         unsigned long data;
617
618         pr_info("%s\n", LCD_DRIVER);
619         ret = misc_register(&lcd_dev);
620         if (ret) {
621                 printk(KERN_WARNING LCD "Unable to register misc device.\n");
622                 return ret;
623         }
624
625         /* Check region? Naaah! Just snarf it up. */
626 /*      request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
627
628         udelay(150);
629         data = LCDReadData;
630         if ((data & 0x000000FF) == (0x00)) {
631                 lcd_present = 0;
632                 pr_info(LCD "LCD Not Present\n");
633         } else {
634                 lcd_present = 1;
635                 WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg);
636                 WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg);
637         }
638
639         return 0;
640 }
641
642 static void __exit lcd_exit(void)
643 {
644         misc_deregister(&lcd_dev);
645 }
646
647 //
648 // Function: dqpoll
649 //
650 // Description:  Polls the data lines to see if the flash is busy
651 //
652 // In: address, byte data
653 //
654 // Out: 0 = busy, 1 = write or erase complete
655 //
656 //
657
658 static int dqpoll(volatile unsigned long address, volatile unsigned char data)
659 {
660         volatile unsigned char dq7;
661
662         dq7 = data & 0x80;
663
664         return ((READ_FLASH(address) & 0x80) == dq7);
665 }
666
667 //
668 // Function: timeout
669 //
670 // Description: Checks to see if erase or write has timed out
671 //              By polling dq5
672 //
673 // In: address
674 //
675 //
676 // Out: 0 = not timed out, 1 = timed out
677
678 static int timeout(volatile unsigned long address)
679 {
680         return (READ_FLASH(address) & 0x20) == 0x20;
681 }
682
683 module_init(lcd_init);
684 module_exit(lcd_exit);
685
686 MODULE_AUTHOR("Andrew Bose");
687 MODULE_LICENSE("GPL");