]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/amcc/taishan/lcd.c
c0a668a95e498466d04e22edfa6e6f1ff2041438
[karo-tx-uboot.git] / board / amcc / taishan / lcd.c
1 /*
2  * (C) Copyright 2007
3  * Stefan Roese, DENX Software Engineering, sr@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+ 
6  */
7
8 #include <config.h>
9 #include <common.h>
10 #include <command.h>
11 #include <i2c.h>
12 #include <miiphy.h>
13
14 #ifdef CONFIG_TAISHAN
15
16 #define LCD_DELAY_NORMAL_US     100
17 #define LCD_DELAY_NORMAL_MS     2
18 #define LCD_CMD_ADDR            ((volatile char *)(CONFIG_SYS_EBC2_LCM_BASE))
19 #define LCD_DATA_ADDR           ((volatile char *)(CONFIG_SYS_EBC2_LCM_BASE+1))
20 #define LCD_BLK_CTRL            ((volatile char *)(CONFIG_SYS_EBC1_FPGA_BASE+0x2))
21
22 static int g_lcd_init_b = 0;
23 static char *amcc_logo = "  AMCC TAISHAN  440GX EvalBoard";
24 static char addr_flag = 0x80;
25
26 static void lcd_bl_ctrl(char val)
27 {
28         char cpld_val;
29
30         cpld_val = *LCD_BLK_CTRL;
31         *LCD_BLK_CTRL = val | cpld_val;
32 }
33
34 static void lcd_putc(char val)
35 {
36         int i = 100;
37         char addr;
38
39         while (i--) {
40                 if ((*LCD_CMD_ADDR & 0x80) != 0x80) {   /*BF = 1 ? */
41                         udelay(LCD_DELAY_NORMAL_US);
42                         break;
43                 }
44                 udelay(LCD_DELAY_NORMAL_US);
45         }
46
47         if (*LCD_CMD_ADDR & 0x80) {
48                 printf("LCD is busy\n");
49                 return;
50         }
51
52         addr = *LCD_CMD_ADDR;
53         udelay(LCD_DELAY_NORMAL_US);
54         if ((addr != 0) && (addr % 0x10 == 0)) {
55                 addr_flag ^= 0x40;
56                 *LCD_CMD_ADDR = addr_flag;
57         }
58
59         udelay(LCD_DELAY_NORMAL_US);
60         *LCD_DATA_ADDR = val;
61         udelay(LCD_DELAY_NORMAL_US);
62 }
63
64 static void lcd_puts(char *s)
65 {
66         char *p = s;
67         int i = 100;
68
69         while (i--) {
70                 if ((*LCD_CMD_ADDR & 0x80) != 0x80) {   /*BF = 1 ? */
71                         udelay(LCD_DELAY_NORMAL_US);
72                         break;
73                 }
74                 udelay(LCD_DELAY_NORMAL_US);
75         }
76
77         if (*LCD_CMD_ADDR & 0x80) {
78                 printf("LCD is busy\n");
79                 return;
80         }
81
82         while (*p)
83                 lcd_putc(*p++);
84 }
85
86 static void lcd_put_logo(void)
87 {
88         int i = 100;
89         char *p = amcc_logo;
90
91         while (i--) {
92                 if ((*LCD_CMD_ADDR & 0x80) != 0x80) {   /*BF = 1 ? */
93                         udelay(LCD_DELAY_NORMAL_US);
94                         break;
95                 }
96                 udelay(LCD_DELAY_NORMAL_US);
97         }
98
99         if (*LCD_CMD_ADDR & 0x80) {
100                 printf("LCD is busy\n");
101                 return;
102         }
103
104         *LCD_CMD_ADDR = 0x80;
105         while (*p)
106                 lcd_putc(*p++);
107 }
108
109 int lcd_init(void)
110 {
111         if (g_lcd_init_b == 0) {
112                 puts("LCD: ");
113                 mdelay(100);    /* Waiting for the LCD initialize */
114
115                 *LCD_CMD_ADDR = 0x38;   /*set function:8-bit,2-line,5x7 font type */
116                 udelay(LCD_DELAY_NORMAL_US);
117
118                 *LCD_CMD_ADDR = 0x0f;   /*set display on,cursor on,blink on */
119                 udelay(LCD_DELAY_NORMAL_US);
120
121                 *LCD_CMD_ADDR = 0x01;   /*display clear */
122                 mdelay(LCD_DELAY_NORMAL_MS);
123
124                 *LCD_CMD_ADDR = 0x06;   /*set entry */
125                 udelay(LCD_DELAY_NORMAL_US);
126
127                 lcd_bl_ctrl(0x02);
128                 lcd_put_logo();
129
130                 puts("  ready\n");
131                 g_lcd_init_b = 1;
132         }
133
134         return 0;
135 }
136
137 static int do_lcd_test(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
138 {
139         lcd_init();
140         return 0;
141 }
142
143 static int do_lcd_clear(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
144 {
145         *LCD_CMD_ADDR = 0x01;
146         mdelay(LCD_DELAY_NORMAL_MS);
147         return 0;
148 }
149 static int do_lcd_puts(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
150 {
151         if (argc < 2)
152                 return cmd_usage(cmdtp);
153
154         lcd_puts(argv[1]);
155         return 0;
156 }
157 static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
158 {
159         if (argc < 2)
160                 return cmd_usage(cmdtp);
161
162         lcd_putc((char)argv[1][0]);
163         return 0;
164 }
165 static int do_lcd_cur(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
166 {
167         ulong count;
168         ulong dir;
169         char cur_addr;
170
171         if (argc < 3)
172                 return cmd_usage(cmdtp);
173
174         count = simple_strtoul(argv[1], NULL, 16);
175         if (count > 31) {
176                 printf("unable to shift > 0x20\n");
177                 count = 0;
178         }
179
180         dir = simple_strtoul(argv[2], NULL, 16);
181         cur_addr = *LCD_CMD_ADDR;
182         udelay(LCD_DELAY_NORMAL_US);
183         if (dir == 0x0) {
184                 if (addr_flag == 0x80) {
185                         if (count >= (cur_addr & 0xf)) {
186                                 *LCD_CMD_ADDR = 0x80;
187                                 udelay(LCD_DELAY_NORMAL_US);
188                                 count = 0;
189                         }
190                 } else {
191                         if (count >= ((cur_addr & 0x0f) + 0x0f)) {
192                                 *LCD_CMD_ADDR = 0x80;
193                                 addr_flag = 0x80;
194                                 udelay(LCD_DELAY_NORMAL_US);
195                                 count = 0x0;
196                         } else if (count >= (cur_addr & 0xf)) {
197                                 count -= cur_addr & 0xf;
198                                 *LCD_CMD_ADDR = 0x80 | 0xf;
199                                 addr_flag = 0x80;
200                                 udelay(LCD_DELAY_NORMAL_US);
201                         }
202                 }
203         } else {
204                 if (addr_flag == 0x80) {
205                         if (count >= (0x1f - (cur_addr & 0xf))) {
206                                 count = 0x0;
207                                 addr_flag = 0xc0;
208                                 *LCD_CMD_ADDR = 0xc0 | 0xf;
209                                 udelay(LCD_DELAY_NORMAL_US);
210                         } else if ((count + (cur_addr & 0xf)) >= 0x0f) {
211                                 count = count + (cur_addr & 0xf) - 0x0f;
212                                 addr_flag = 0xc0;
213                                 *LCD_CMD_ADDR = 0xc0;
214                                 udelay(LCD_DELAY_NORMAL_US);
215                         }
216                 } else if ((count + (cur_addr & 0xf)) >= 0x0f) {
217                         count = 0x0;
218                         *LCD_CMD_ADDR = 0xc0 | 0xf;
219                         udelay(LCD_DELAY_NORMAL_US);
220                 }
221         }
222
223         while (count--) {
224                 if (dir == 0) {
225                         *LCD_CMD_ADDR = 0x10;
226                 } else {
227                         *LCD_CMD_ADDR = 0x14;
228                 }
229                 udelay(LCD_DELAY_NORMAL_US);
230         }
231
232         return 0;
233 }
234
235 U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd test display", "");
236 U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd clear display", "");
237 U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts,
238            "display string on lcd",
239            "<string> - <string> to be displayed");
240 U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc,
241            "display char on lcd",
242            "<char> - <char> to be displayed");
243 U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur,
244            "shift cursor on lcd",
245            "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n"
246            " <count> - 0~31\n" " <dir> - 0,backward; 1, forward");
247
248 #if 0 /* test-only */
249 void set_phy_loopback_mode(void)
250 {
251         char devemac2[32];
252         char devemac3[32];
253
254         sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
255         sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);
256
257 #if 0
258         unsigned short reg_short;
259
260         miiphy_read(devemac2, 0x1, 1, &reg_short);
261         if (reg_short & 0x04) {
262                 /*
263                  * printf("EMAC2 link up,do nothing\n");
264                  */
265         } else {
266                 udelay(1000);
267                 miiphy_write(devemac2, 0x1, 0, 0x6000);
268                 udelay(1000);
269                 miiphy_read(devemac2, 0x1, 0, &reg_short);
270                 if (reg_short != 0x6000) {
271                         printf
272                             ("\nEMAC2 error set LOOPBACK mode error,reg2[0]=%x\n",
273                              reg_short);
274                 }
275         }
276
277         miiphy_read(devemac3, 0x3, 1, &reg_short);
278         if (reg_short & 0x04) {
279                 /*
280                  * printf("EMAC3 link up,do nothing\n");
281                  */
282         } else {
283                 udelay(1000);
284                 miiphy_write(devemac3, 0x3, 0, 0x6000);
285                 udelay(1000);
286                 miiphy_read(devemac3, 0x3, 0, &reg_short);
287                 if (reg_short != 0x6000) {
288                         printf
289                             ("\nEMAC3 error set LOOPBACK mode error,reg2[0]=%x\n",
290                              reg_short);
291                 }
292         }
293 #else
294         /* Set PHY as LOOPBACK MODE, for Linux emac initializing */
295         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0, 0x6000);
296         udelay(1000);
297         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0, 0x6000);
298         udelay(1000);
299 #endif  /* 0 */
300 }
301
302 void set_phy_normal_mode(void)
303 {
304         char devemac2[32];
305         char devemac3[32];
306         unsigned short reg_short;
307
308         sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
309         sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);
310
311         /* Set phy of EMAC2 */
312         miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x16, &reg_short);
313         reg_short &= ~(0x7);
314         reg_short |= 0x6;       /* RGMII DLL Delay */
315         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x16, reg_short);
316
317         miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x17, &reg_short);
318         reg_short &= ~(0x40);
319         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x17, reg_short);
320
321         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x1c, 0x74f0);
322
323         /* Set phy of EMAC3 */
324         miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x16, &reg_short);
325         reg_short &= ~(0x7);
326         reg_short |= 0x6;       /* RGMII DLL Delay */
327         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x16, reg_short);
328
329         miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x17, &reg_short);
330         reg_short &= ~(0x40);
331         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x17, reg_short);
332
333         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x1c, 0x74f0);
334 }
335 #endif  /* 0 - test only */
336
337 static int do_led_test_off(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
338 {
339         volatile unsigned int *GpioOr =
340                 (volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
341         *GpioOr |= 0x00300000;
342         return 0;
343 }
344
345 static int do_led_test_on(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
346 {
347         volatile unsigned int *GpioOr =
348                 (volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
349         *GpioOr &= ~0x00300000;
350         return 0;
351 }
352
353 U_BOOT_CMD(ledon, 1, 1, do_led_test_on,
354            "led test light on", "");
355
356 U_BOOT_CMD(ledoff, 1, 1, do_led_test_off,
357            "led test light off", "");
358 #endif