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