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