lcd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:13k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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. #define RTC_IO_EXTENT 0x10    /*Only really two ports, but... */
  15. #include <linux/types.h>
  16. #include <linux/errno.h>
  17. #include <linux/miscdevice.h>
  18. #include <linux/slab.h>
  19. #include <linux/ioport.h>
  20. #include <linux/fcntl.h>
  21. #include <linux/mc146818rtc.h>
  22. #include <linux/netdevice.h>
  23. #include <linux/sched.h>
  24. #include <asm/io.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/system.h>
  27. #include <linux/delay.h>
  28. #include "lcd.h"
  29. static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
  30.                      unsigned long arg);
  31. static int lcd_present = 1;
  32. int led_state = 0;
  33. #if defined(CONFIG_TULIP) && 0
  34. #define MAX_INTERFACES 8
  35. static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES];
  36. static void *linkcheck_cookies[MAX_INTERFACES];
  37. int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie)
  38. {
  39. if (iface_num < 0 ||
  40.     iface_num >= MAX_INTERFACES ||
  41.     linkcheck_callbacks[iface_num] != NULL)
  42. return -1;
  43. linkcheck_callbacks[iface_num] = (linkcheck_func_t) func;
  44. linkcheck_cookies[iface_num] = cookie;
  45. return 0;
  46. }
  47. #endif
  48. static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
  49. unsigned long arg)
  50. {
  51. struct lcd_display button_display;
  52. unsigned long address, a;
  53. int index;
  54. switch (cmd) {
  55. case LCD_On:
  56. udelay(150);
  57. BusyCheck();
  58. LCDWriteInst(0x0F);
  59. break;
  60. case LCD_Off:
  61. udelay(150);
  62. BusyCheck();
  63. LCDWriteInst(0x08);
  64. break;
  65. case LCD_Reset:
  66. udelay(150);
  67. LCDWriteInst(0x3F);
  68. udelay(150);
  69. LCDWriteInst(0x3F);
  70. udelay(150);
  71. LCDWriteInst(0x3F);
  72. udelay(150);
  73. LCDWriteInst(0x3F);
  74. udelay(150);
  75. LCDWriteInst(0x01);
  76. udelay(150);
  77. LCDWriteInst(0x06);
  78. break;
  79. case LCD_Clear:
  80. udelay(150);
  81. BusyCheck();
  82.         LCDWriteInst(0x01);     
  83. break;
  84. case LCD_Cursor_Left:
  85. udelay(150);
  86. BusyCheck();
  87. LCDWriteInst(0x10);
  88. break;
  89. case LCD_Cursor_Right:
  90. udelay(150);
  91. BusyCheck();
  92. LCDWriteInst(0x14);
  93. break;
  94. case LCD_Cursor_Off:
  95. udelay(150);
  96.                 BusyCheck();
  97.                 LCDWriteInst(0x0C);
  98.         break;
  99.         case LCD_Cursor_On:
  100.                 udelay(150);
  101.                 BusyCheck();
  102.                 LCDWriteInst(0x0F);
  103.                 break;
  104.         case LCD_Blink_Off:
  105.                 udelay(150);
  106.                 BusyCheck();
  107.                 LCDWriteInst(0x0E);
  108.                 break;
  109. case LCD_Get_Cursor_Pos:{
  110.                 struct lcd_display display;
  111. udelay(150);
  112.                 BusyCheck();
  113. display.cursor_address = ( LCDReadInst ); 
  114. display.cursor_address = ( display.cursor_address & 0x07F );
  115. if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display)))
  116.   return -EFAULT;
  117. break;
  118. }
  119. case LCD_Set_Cursor_Pos: {
  120.                 struct lcd_display display;
  121.                 if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
  122.   return -EFAULT;
  123. a = (display.cursor_address | kLCD_Addr ); 
  124.                 udelay(150);
  125.                 BusyCheck();    
  126.                 LCDWriteInst( a );
  127.                 break;
  128. }
  129. case LCD_Get_Cursor: {
  130.                 struct lcd_display display;
  131.                 udelay(150);
  132.                 BusyCheck();    
  133. display.character = LCDReadData;
  134. if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display)))
  135.   return -EFAULT;
  136.                 udelay(150);
  137.                 BusyCheck();
  138.                 LCDWriteInst(0x10);
  139. break;
  140. }
  141. case LCD_Set_Cursor:{
  142.                 struct lcd_display display;
  143.    
  144.                 if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
  145.   return -EFAULT;
  146.                 udelay(150);
  147. BusyCheck();    
  148.                 LCDWriteData( display.character );
  149.                 udelay(150);
  150.                 BusyCheck();
  151.                 LCDWriteInst(0x10);
  152.                 break;
  153.                 }
  154. case LCD_Disp_Left:
  155. udelay(150);
  156. BusyCheck();
  157. LCDWriteInst(0x18);
  158. break;
  159. case LCD_Disp_Right:
  160. udelay(150);
  161. BusyCheck();
  162. LCDWriteInst(0x1C);
  163. break;
  164. case LCD_Home:
  165. udelay(150);
  166. BusyCheck();
  167. LCDWriteInst(0x02);
  168. break;
  169. case LCD_Write: {
  170. struct lcd_display display;
  171.    
  172.                 if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
  173.   return -EFAULT;
  174.  
  175. udelay(150);
  176.                 BusyCheck();    
  177.                 LCDWriteInst(0x80);
  178. udelay(150);
  179. BusyCheck();
  180. for (index = 0; index < (display.size1); index++) {
  181. udelay(150);
  182. BusyCheck();
  183. LCDWriteData( display.line1[index]);
  184. BusyCheck();
  185. }
  186. udelay(150);
  187. BusyCheck();
  188. LCDWriteInst(0xC0);
  189. udelay(150);
  190. BusyCheck();
  191.                 for (index = 0; index < (display.size2); index++) {
  192.                         udelay(150);
  193.                         BusyCheck();    
  194.                         LCDWriteData( display.line2[index]);
  195. }
  196.  
  197. break;
  198. }
  199. case LCD_Read: {
  200.          struct lcd_display display;
  201. BusyCheck();
  202. for (address = kDD_R00; address <= kDD_R01; address++) {
  203. a = (address | kLCD_Addr );
  204. udelay(150);
  205. BusyCheck();
  206. LCDWriteInst( a );
  207. udelay(150);
  208. BusyCheck();
  209. display.line1[address] = LCDReadData;
  210. }
  211. display.line1[ 0x27 ] = '';
  212. for (address = kDD_R10; address <= kDD_R11; address++) {
  213. a = (address | kLCD_Addr );     
  214.         
  215. udelay(150);
  216.   BusyCheck();
  217.          LCDWriteInst( a );
  218.        
  219.          udelay(150);
  220.   BusyCheck();
  221.          display.line2[address - 0x40 ] = LCDReadData;
  222.  }
  223. display.line2[ 0x27 ] = '';
  224. if(copy_to_user((struct lcd_display*)arg, &display,
  225. sizeof(struct lcd_display)))
  226.   return -EFAULT;
  227. break;
  228. }
  229. //  set all GPIO leds to led_display.leds 
  230. case LED_Set: {
  231. struct lcd_display led_display;
  232.         if(copy_from_user(&led_display, (struct lcd_display*)arg,
  233.   sizeof(struct lcd_display)))
  234.   return -EFAULT;
  235. led_state = led_display.leds;
  236. LEDSet(led_state);
  237.          break;
  238. }
  239. //  set only bit led_display.leds
  240.         case LED_Bit_Set: {
  241.                 int i;
  242. int bit=1;
  243.                 struct lcd_display led_display;
  244.                 if(copy_from_user(&led_display, (struct lcd_display*)arg,
  245.   sizeof(struct lcd_display)))
  246.   return -EFAULT;
  247. for (i=0;i<(int)led_display.leds;i++)
  248. {
  249. bit = 2*bit;
  250. }
  251. led_state = led_state | bit;
  252.                 LEDSet(led_state);
  253.                 break;
  254.         }
  255. //  clear only bit led_display.leds
  256.         case LED_Bit_Clear: {
  257.                 int i;
  258. int bit=1;
  259.                 struct lcd_display led_display;
  260.                 if(copy_from_user(&led_display, (struct lcd_display*)arg,
  261.   sizeof(struct lcd_display)))
  262.   return -EFAULT;
  263.                 for (i=0;i<(int)led_display.leds;i++)
  264.                         {
  265.                                 bit = 2*bit;
  266.                         }
  267. led_state = led_state &  ~bit;
  268.                 LEDSet(led_state);
  269.                 break;
  270.         }
  271. case BUTTON_Read: {
  272. button_display.buttons = GPIRead;
  273.                 if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display)))
  274.   return -EFAULT;
  275. break;
  276. }
  277.         case LINK_Check: {
  278.                 button_display.buttons = *((volatile unsigned long *) (0xB0100060) );
  279.                 if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display)))
  280.   return -EFAULT;
  281.                 break;
  282.         }
  283. case LINK_Check_2: {
  284. int iface_num;
  285. /* panel-utils should pass in the desired interface status is wanted for
  286.  * in "buttons" of the structure.  We will set this to non-zero if the
  287.  * link is in fact up for the requested interface.  --DaveM
  288.  */
  289. if(copy_from_user(&button_display, (struct lcd_display *)arg, sizeof(button_display)))
  290.   return -EFAULT;
  291. iface_num = button_display.buttons;
  292. #if defined(CONFIG_TULIP) && 0
  293. if (iface_num >= 0 &&
  294.     iface_num < MAX_INTERFACES &&
  295.     linkcheck_callbacks[iface_num] != NULL) {
  296. button_display.buttons =
  297. linkcheck_callbacks[iface_num](linkcheck_cookies[iface_num]);
  298. } else
  299. #endif
  300. button_display.buttons = 0;
  301.                 if(__copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display)))
  302.   return -EFAULT;
  303.                 break;
  304. }
  305. //  Erase the flash
  306. case FLASH_Erase: {
  307. int ctr=0;
  308.     // Chip Erase Sequence
  309. WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
  310. WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
  311. WRITE_FLASH( kFlash_Addr1, kFlash_Erase3 );
  312. WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
  313. WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
  314. WRITE_FLASH( kFlash_Addr1, kFlash_Erase6 );
  315. printk( "Erasing Flash.n");
  316. while ( (!dqpoll(0x00000000,0xFF)) && (!timeout(0x00000000)) ) {
  317.     ctr++;
  318. }
  319. printk("n");
  320. printk("n");
  321. printk("n");
  322. if (READ_FLASH(0x07FFF0)==0xFF) { printk("Erase Successfulrn"); }
  323. else if (timeout) { printk("Erase Timed Outrn"); }
  324. break;
  325. }
  326. // burn the flash 
  327. case FLASH_Burn: {
  328. volatile unsigned long burn_addr;
  329. unsigned long flags;
  330. int i;
  331. unsigned char *rom;
  332.                 struct lcd_display display;
  333.                 if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
  334.   return -EFAULT;
  335. rom = (unsigned char *) kmalloc((128),GFP_ATOMIC);
  336.                 if ( rom == NULL ) {
  337.                        printk ("brokenn");
  338.                        return 1;
  339.                    }
  340. printk("Churning and Burning -");
  341. save_flags(flags);
  342. for (i=0; i<FLASH_SIZE; i=i+128) {
  343.         if(copy_from_user(rom, display.RomImage + i, 128))
  344.    return -EFAULT;
  345. burn_addr = kFlashBase + i;
  346. cli();
  347. for ( index = 0; index < ( 128 ) ; index++ ) 
  348.      {
  349. WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
  350.        WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
  351.        WRITE_FLASH( kFlash_Addr1, kFlash_Prog );
  352.        *((volatile unsigned char *)burn_addr) = (volatile unsigned char) rom[index];
  353.        while ( (!dqpoll(burn_addr,(volatile unsigned char) rom[index])) && (!timeout(burn_addr)) ) {
  354.        }
  355.        burn_addr++;
  356.      }
  357. restore_flags(flags);
  358.                  if ( *((volatile unsigned char *)(burn_addr-1)) == (volatile unsigned char) rom[index-1]  ) {
  359.                  } else if (timeout) {
  360.                      printk("Program timed outrn");
  361.                  }
  362. }
  363. kfree(rom);
  364. break;
  365. }
  366. //  read the flash all at once 
  367. case FLASH_Read: {
  368. unsigned char *user_bytes;
  369.                 volatile unsigned long read_addr;
  370.                 int i;
  371. user_bytes = &(((struct lcd_display *)arg)->RomImage[0]);
  372. if(!access_ok(VERIFY_WRITE, user_bytes, FLASH_SIZE))
  373.                          return -EFAULT;
  374. printk("Reading Flash");
  375. for (i=0; i<FLASH_SIZE; i++) {
  376. unsigned char tmp_byte;
  377. read_addr = kFlashBase + i;
  378. tmp_byte = *((volatile unsigned char *)read_addr);
  379. if(__put_user (tmp_byte, &user_bytes[i]))
  380.   return -EFAULT;
  381. }
  382. break;
  383. }
  384. default:
  385. return 0;
  386. break;
  387. }
  388. return 0;
  389. }
  390. static int lcd_open(struct inode *inode, struct file *file)
  391. {
  392. if (!lcd_present)
  393. return -ENXIO;
  394. else
  395. return 0;
  396. }
  397. /* Only RESET or NEXT counts as button pressed */
  398. static inline int button_pressed(void)
  399. {
  400. unsigned long buttons = GPIRead;
  401. if ( (buttons == BUTTON_Next) || (buttons == BUTTON_Next_B) || (buttons == BUTTON_Reset_B) )
  402. return buttons;
  403. return 0;
  404. }
  405. /* LED daemon sits on this and we wake him up once a key is pressed. */
  406. static int lcd_waiters = 0;
  407. static long lcd_read(struct inode *inode, struct file *file, char *buf, unsigned long count)
  408. {
  409. long buttons_now;
  410. if(lcd_waiters > 0)
  411. return -EINVAL;
  412. lcd_waiters++;
  413. while(((buttons_now = (long)button_pressed()) == 0) &&
  414.       !(signal_pending(current))) {
  415. current->state = TASK_INTERRUPTIBLE;
  416. schedule_timeout(2 * HZ);
  417. }
  418. lcd_waiters--;
  419. if(signal_pending(current))
  420. return -ERESTARTSYS;
  421. return buttons_now;
  422. }
  423. /*
  424.  * The various file operations we support.
  425.  */
  426. static struct file_operations lcd_fops = {
  427. read: lcd_read,
  428. ioctl: lcd_ioctl,
  429. open: lcd_open,
  430. };
  431. static struct miscdevice lcd_dev=
  432. {
  433. LCD_MINOR,
  434. "lcd",
  435. &lcd_fops
  436. };
  437. int lcd_init(void)
  438. {
  439. unsigned long data;
  440. printk("%sn", LCD_DRIVER);
  441. misc_register(&lcd_dev);
  442. /* Check region? Naaah! Just snarf it up. */
  443. /* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
  444. udelay(150);
  445. data = LCDReadData;
  446. if ( (data & 0x000000FF) == (0x00) ) {
  447. lcd_present = 0;
  448. printk("LCD Not Presentn");
  449.         }
  450. else {
  451. lcd_present = 1;
  452. WRITE_GAL( kGal_DevBank2PReg, kGal_DevBank2Cfg );
  453. WRITE_GAL( kGal_DevBank3PReg, kGal_DevBank3Cfg );
  454. }
  455. return 0;
  456. }
  457. //
  458. // Function: dqpoll
  459. //
  460. // Description:  Polls the data lines to see if the flash is busy
  461. //
  462. // In: address, byte data
  463. //
  464. // Out: 0 = busy, 1 = write or erase complete
  465. //
  466. //
  467. int dqpoll( volatile unsigned long address, volatile unsigned char data ) {
  468. volatile unsigned char dq7;
  469. dq7 = data & 0x80;
  470. return ( (READ_FLASH(address) & 0x80) == dq7  );
  471. }
  472. //
  473. // Function: timeout
  474. //
  475. // Description: Checks to see if erase or write has timed out
  476. //              By polling dq5
  477. //
  478. // In: address
  479. //
  480. //
  481. // Out: 0 = not timed out, 1 = timed out
  482. int timeout( volatile unsigned long address ) {
  483. return (  (READ_FLASH(address) & 0x20) ==  0x20 );
  484. }