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