Merge ../master/
[oweals/u-boot.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 *)(CFG_EBC2_LCM_BASE))
35 #define LCD_DATA_ADDR           ((volatile char *)(CFG_EBC2_LCM_BASE+1))
36 #define LCD_BLK_CTRL            ((volatile char *)(CFG_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 *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 *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 *argv[])
168 {
169         if (argc < 2) {
170                 printf("%s", cmdtp->usage);
171                 return 1;
172         }
173         lcd_puts(argv[1]);
174         return 0;
175 }
176 static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
177 {
178         if (argc < 2) {
179                 printf("%s", cmdtp->usage);
180                 return 1;
181         }
182         lcd_putc((char)argv[1][0]);
183         return 0;
184 }
185 static int do_lcd_cur(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
186 {
187         ulong count;
188         ulong dir;
189         char cur_addr;
190
191         if (argc < 3) {
192                 printf("%s", cmdtp->usage);
193                 return 1;
194         }
195
196         count = simple_strtoul(argv[1], NULL, 16);
197         if (count > 31) {
198                 printf("unable to shift > 0x20\n");
199                 count = 0;
200         }
201
202         dir = simple_strtoul(argv[2], NULL, 16);
203         cur_addr = *LCD_CMD_ADDR;
204         udelay(LCD_DELAY_NORMAL_US);
205         if (dir == 0x0) {
206                 if (addr_flag == 0x80) {
207                         if (count >= (cur_addr & 0xf)) {
208                                 *LCD_CMD_ADDR = 0x80;
209                                 udelay(LCD_DELAY_NORMAL_US);
210                                 count = 0;
211                         }
212                 } else {
213                         if (count >= ((cur_addr & 0x0f) + 0x0f)) {
214                                 *LCD_CMD_ADDR = 0x80;
215                                 addr_flag = 0x80;
216                                 udelay(LCD_DELAY_NORMAL_US);
217                                 count = 0x0;
218                         } else if (count >= (cur_addr & 0xf)) {
219                                 count -= cur_addr & 0xf;
220                                 *LCD_CMD_ADDR = 0x80 | 0xf;
221                                 addr_flag = 0x80;
222                                 udelay(LCD_DELAY_NORMAL_US);
223                         }
224                 }
225         } else {
226                 if (addr_flag == 0x80) {
227                         if (count >= (0x1f - (cur_addr & 0xf))) {
228                                 count = 0x0;
229                                 addr_flag = 0xc0;
230                                 *LCD_CMD_ADDR = 0xc0 | 0xf;
231                                 udelay(LCD_DELAY_NORMAL_US);
232                         } else if ((count + (cur_addr & 0xf)) >= 0x0f) {
233                                 count = count + (cur_addr & 0xf) - 0x0f;
234                                 addr_flag = 0xc0;
235                                 *LCD_CMD_ADDR = 0xc0;
236                                 udelay(LCD_DELAY_NORMAL_US);
237                         }
238                 } else if ((count + (cur_addr & 0xf)) >= 0x0f) {
239                         count = 0x0;
240                         *LCD_CMD_ADDR = 0xc0 | 0xf;
241                         udelay(LCD_DELAY_NORMAL_US);
242                 }
243         }
244
245         while (count--) {
246                 if (dir == 0) {
247                         *LCD_CMD_ADDR = 0x10;
248                 } else {
249                         *LCD_CMD_ADDR = 0x14;
250                 }
251                 udelay(LCD_DELAY_NORMAL_US);
252         }
253
254         return 0;
255 }
256
257 U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd_test - lcd test display\n", NULL);
258 U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd_cls - lcd clear display\n", NULL);
259 U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts,
260            "lcd_puts - display string on lcd\n",
261            "<string> - <string> to be displayed\n");
262 U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc,
263            "lcd_putc - display char on lcd\n",
264            "<char> - <char> to be displayed\n");
265 U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur,
266            "lcd_cur - shift cursor on lcd\n",
267            "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n"
268            " <count> - 0~31\n" " <dir> - 0,backward; 1, forward\n");
269
270 #if 0 /* test-only */
271 void set_phy_loopback_mode(void)
272 {
273         char devemac2[32];
274         char devemac3[32];
275
276         sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
277         sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);
278
279 #if 0
280         unsigned short reg_short;
281
282         miiphy_read(devemac2, 0x1, 1, &reg_short);
283         if (reg_short & 0x04) {
284                 /*
285                  * printf("EMAC2 link up,do nothing\n");
286                  */
287         } else {
288                 udelay(1000);
289                 miiphy_write(devemac2, 0x1, 0, 0x6000);
290                 udelay(1000);
291                 miiphy_read(devemac2, 0x1, 0, &reg_short);
292                 if (reg_short != 0x6000) {
293                         printf
294                             ("\nEMAC2 error set LOOPBACK mode error,reg2[0]=%x\n",
295                              reg_short);
296                 }
297         }
298
299         miiphy_read(devemac3, 0x3, 1, &reg_short);
300         if (reg_short & 0x04) {
301                 /*
302                  * printf("EMAC3 link up,do nothing\n");
303                  */
304         } else {
305                 udelay(1000);
306                 miiphy_write(devemac3, 0x3, 0, 0x6000);
307                 udelay(1000);
308                 miiphy_read(devemac3, 0x3, 0, &reg_short);
309                 if (reg_short != 0x6000) {
310                         printf
311                             ("\nEMAC3 error set LOOPBACK mode error,reg2[0]=%x\n",
312                              reg_short);
313                 }
314         }
315 #else
316         /* Set PHY as LOOPBACK MODE, for Linux emac initializing */
317         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0, 0x6000);
318         udelay(1000);
319         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0, 0x6000);
320         udelay(1000);
321 #endif  /* 0 */
322 }
323
324 void set_phy_normal_mode(void)
325 {
326         char devemac2[32];
327         char devemac3[32];
328         unsigned short reg_short;
329
330         sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
331         sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);
332
333         /* Set phy of EMAC2 */
334         miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x16, &reg_short);
335         reg_short &= ~(0x7);
336         reg_short |= 0x6;       /* RGMII DLL Delay */
337         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x16, reg_short);
338
339         miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x17, &reg_short);
340         reg_short &= ~(0x40);
341         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x17, reg_short);
342
343         miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x1c, 0x74f0);
344
345         /* Set phy of EMAC3 */
346         miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x16, &reg_short);
347         reg_short &= ~(0x7);
348         reg_short |= 0x6;       /* RGMII DLL Delay */
349         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x16, reg_short);
350
351         miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x17, &reg_short);
352         reg_short &= ~(0x40);
353         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x17, reg_short);
354
355         miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x1c, 0x74f0);
356 }
357 #endif  /* 0 - test only */
358
359 static int do_led_test_off(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
360 {
361         volatile unsigned int *GpioOr =
362                 (volatile unsigned int *)(CFG_PERIPHERAL_BASE + 0x700);
363         *GpioOr |= 0x00300000;
364         return 0;
365 }
366
367 static int do_led_test_on(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
368 {
369         volatile unsigned int *GpioOr =
370                 (volatile unsigned int *)(CFG_PERIPHERAL_BASE + 0x700);
371         *GpioOr &= ~0x00300000;
372         return 0;
373 }
374
375 U_BOOT_CMD(ledon, 1, 1, do_led_test_on,
376            "ledon - led test light on\n", NULL);
377
378 U_BOOT_CMD(ledoff, 1, 1, do_led_test_off,
379            "ledoff - led test light off\n", NULL);
380 #endif