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