Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 1 | /* |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 2 | * Driver for the LCD display on the Tensilica XTFPGA board family. |
| 3 | * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 4 | * |
| 5 | * This file is subject to the terms and conditions of the GNU General Public |
| 6 | * License. See the file "COPYING" in the main directory of this archive |
| 7 | * for more details. |
| 8 | * |
| 9 | * Copyright (C) 2001, 2006 Tensilica Inc. |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 10 | * Copyright (C) 2015 Cadence Design Systems Inc. |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 11 | */ |
| 12 | |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 13 | #include <linux/delay.h> |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 14 | #include <linux/init.h> |
| 15 | #include <linux/io.h> |
| 16 | |
| 17 | #include <platform/hardware.h> |
| 18 | #include <platform/lcd.h> |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 19 | |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 20 | /* LCD instruction and data addresses. */ |
| 21 | #define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR)) |
| 22 | #define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4) |
| 23 | |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 24 | #define LCD_CLEAR 0x1 |
| 25 | #define LCD_DISPLAY_ON 0xc |
| 26 | |
| 27 | /* 8bit and 2 lines display */ |
| 28 | #define LCD_DISPLAY_MODE8BIT 0x38 |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 29 | #define LCD_DISPLAY_MODE4BIT 0x28 |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 30 | #define LCD_DISPLAY_POS 0x80 |
| 31 | #define LCD_SHIFT_LEFT 0x18 |
| 32 | #define LCD_SHIFT_RIGHT 0x1c |
| 33 | |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 34 | static void lcd_put_byte(u8 *addr, u8 data) |
| 35 | { |
| 36 | #ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame^] | 37 | WRITE_ONCE(*addr, data); |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 38 | #else |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame^] | 39 | WRITE_ONCE(*addr, data & 0xf0); |
| 40 | WRITE_ONCE(*addr, (data << 4) & 0xf0); |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 41 | #endif |
| 42 | } |
| 43 | |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 44 | static int __init lcd_init(void) |
| 45 | { |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame^] | 46 | WRITE_ONCE(*LCD_INSTR_ADDR, LCD_DISPLAY_MODE8BIT); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 47 | mdelay(5); |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame^] | 48 | WRITE_ONCE(*LCD_INSTR_ADDR, LCD_DISPLAY_MODE8BIT); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 49 | udelay(200); |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame^] | 50 | WRITE_ONCE(*LCD_INSTR_ADDR, LCD_DISPLAY_MODE8BIT); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 51 | udelay(50); |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 52 | #ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS |
Mark Rutland | 6aa7de0 | 2017-10-23 14:07:29 -0700 | [diff] [blame^] | 53 | WRITE_ONCE(*LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 54 | udelay(50); |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 55 | lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT); |
| 56 | udelay(50); |
| 57 | #endif |
| 58 | lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON); |
| 59 | udelay(50); |
| 60 | lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 61 | mdelay(10); |
| 62 | lcd_disp_at_pos("XTENSA LINUX", 0); |
| 63 | return 0; |
| 64 | } |
| 65 | |
| 66 | void lcd_disp_at_pos(char *str, unsigned char pos) |
| 67 | { |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 68 | lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 69 | udelay(100); |
| 70 | while (*str != 0) { |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 71 | lcd_put_byte(LCD_DATA_ADDR, *str); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 72 | udelay(200); |
| 73 | str++; |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | void lcd_shiftleft(void) |
| 78 | { |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 79 | lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 80 | udelay(50); |
| 81 | } |
| 82 | |
| 83 | void lcd_shiftright(void) |
| 84 | { |
Max Filippov | 4949009 | 2015-02-27 06:28:00 +0300 | [diff] [blame] | 85 | lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT); |
Max Filippov | 0d456ba | 2012-11-05 07:37:14 +0400 | [diff] [blame] | 86 | udelay(50); |
| 87 | } |
| 88 | |
| 89 | arch_initcall(lcd_init); |