diff options
Diffstat (limited to 'arch/xtensa/platforms/xtfpga/lcd.c')
-rw-r--r-- | arch/xtensa/platforms/xtfpga/lcd.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/arch/xtensa/platforms/xtfpga/lcd.c b/arch/xtensa/platforms/xtfpga/lcd.c index 2872301598df..4dc0c1b43f4b 100644 --- a/arch/xtensa/platforms/xtfpga/lcd.c +++ b/arch/xtensa/platforms/xtfpga/lcd.c | |||
@@ -1,50 +1,63 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for the LCD display on the Tensilica LX60 Board. | 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 | ||
3 | * | 4 | * |
4 | * This file is subject to the terms and conditions of the GNU General Public | 5 | * 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 | * License. See the file "COPYING" in the main directory of this archive |
6 | * for more details. | 7 | * for more details. |
7 | * | 8 | * |
8 | * Copyright (C) 2001, 2006 Tensilica Inc. | 9 | * Copyright (C) 2001, 2006 Tensilica Inc. |
10 | * Copyright (C) 2015 Cadence Design Systems Inc. | ||
9 | */ | 11 | */ |
10 | 12 | ||
11 | /* | 13 | #include <linux/delay.h> |
12 | * | ||
13 | * FIXME: this code is from the examples from the LX60 user guide. | ||
14 | * | ||
15 | * The lcd_pause function does busy waiting, which is probably not | ||
16 | * great. Maybe the code could be changed to use kernel timers, or | ||
17 | * change the hardware to not need to wait. | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | 14 | #include <linux/init.h> |
21 | #include <linux/io.h> | 15 | #include <linux/io.h> |
22 | 16 | ||
23 | #include <platform/hardware.h> | 17 | #include <platform/hardware.h> |
24 | #include <platform/lcd.h> | 18 | #include <platform/lcd.h> |
25 | #include <linux/delay.h> | ||
26 | 19 | ||
27 | #define LCD_PAUSE_ITERATIONS 4000 | 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 | |||
28 | #define LCD_CLEAR 0x1 | 24 | #define LCD_CLEAR 0x1 |
29 | #define LCD_DISPLAY_ON 0xc | 25 | #define LCD_DISPLAY_ON 0xc |
30 | 26 | ||
31 | /* 8bit and 2 lines display */ | 27 | /* 8bit and 2 lines display */ |
32 | #define LCD_DISPLAY_MODE8BIT 0x38 | 28 | #define LCD_DISPLAY_MODE8BIT 0x38 |
29 | #define LCD_DISPLAY_MODE4BIT 0x28 | ||
33 | #define LCD_DISPLAY_POS 0x80 | 30 | #define LCD_DISPLAY_POS 0x80 |
34 | #define LCD_SHIFT_LEFT 0x18 | 31 | #define LCD_SHIFT_LEFT 0x18 |
35 | #define LCD_SHIFT_RIGHT 0x1c | 32 | #define LCD_SHIFT_RIGHT 0x1c |
36 | 33 | ||
34 | static void lcd_put_byte(u8 *addr, u8 data) | ||
35 | { | ||
36 | #ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS | ||
37 | ACCESS_ONCE(*addr) = data; | ||
38 | #else | ||
39 | ACCESS_ONCE(*addr) = data & 0xf0; | ||
40 | ACCESS_ONCE(*addr) = (data << 4) & 0xf0; | ||
41 | #endif | ||
42 | } | ||
43 | |||
37 | static int __init lcd_init(void) | 44 | static int __init lcd_init(void) |
38 | { | 45 | { |
39 | *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; | 46 | ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; |
40 | mdelay(5); | 47 | mdelay(5); |
41 | *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; | 48 | ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; |
42 | udelay(200); | 49 | udelay(200); |
43 | *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; | 50 | ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; |
51 | udelay(50); | ||
52 | #ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS | ||
53 | ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT; | ||
54 | udelay(50); | ||
55 | lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT); | ||
44 | udelay(50); | 56 | udelay(50); |
45 | *LCD_INSTR_ADDR = LCD_DISPLAY_ON; | 57 | #endif |
58 | lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON); | ||
46 | udelay(50); | 59 | udelay(50); |
47 | *LCD_INSTR_ADDR = LCD_CLEAR; | 60 | lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR); |
48 | mdelay(10); | 61 | mdelay(10); |
49 | lcd_disp_at_pos("XTENSA LINUX", 0); | 62 | lcd_disp_at_pos("XTENSA LINUX", 0); |
50 | return 0; | 63 | return 0; |
@@ -52,10 +65,10 @@ static int __init lcd_init(void) | |||
52 | 65 | ||
53 | void lcd_disp_at_pos(char *str, unsigned char pos) | 66 | void lcd_disp_at_pos(char *str, unsigned char pos) |
54 | { | 67 | { |
55 | *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos; | 68 | lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos); |
56 | udelay(100); | 69 | udelay(100); |
57 | while (*str != 0) { | 70 | while (*str != 0) { |
58 | *LCD_DATA_ADDR = *str; | 71 | lcd_put_byte(LCD_DATA_ADDR, *str); |
59 | udelay(200); | 72 | udelay(200); |
60 | str++; | 73 | str++; |
61 | } | 74 | } |
@@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos) | |||
63 | 76 | ||
64 | void lcd_shiftleft(void) | 77 | void lcd_shiftleft(void) |
65 | { | 78 | { |
66 | *LCD_INSTR_ADDR = LCD_SHIFT_LEFT; | 79 | lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT); |
67 | udelay(50); | 80 | udelay(50); |
68 | } | 81 | } |
69 | 82 | ||
70 | void lcd_shiftright(void) | 83 | void lcd_shiftright(void) |
71 | { | 84 | { |
72 | *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT; | 85 | lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT); |
73 | udelay(50); | 86 | udelay(50); |
74 | } | 87 | } |
75 | 88 | ||