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