blob: 124b81ee0bca73e9ca72e6a65a9b6502eea22eef [file] [log] [blame]
Stefan Roese5fb692c2007-01-18 10:25:34 +01001/*
2 * (C) Copyright 2007
3 * Stefan Roese, DENX Software Engineering, sr@denx.de.
4 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +02005 * SPDX-License-Identifier: GPL-2.0+
Stefan Roese5fb692c2007-01-18 10:25:34 +01006 */
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
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020018#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))
Stefan Roese5fb692c2007-01-18 10:25:34 +010021
Stefan Roese5fb692c2007-01-18 10:25:34 +010022static int g_lcd_init_b = 0;
23static char *amcc_logo = " AMCC TAISHAN 440GX EvalBoard";
24static char addr_flag = 0x80;
25
26static 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
34static 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
64static 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
86static 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
109int 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
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200137static int do_lcd_test(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100138{
139 lcd_init();
140 return 0;
141}
142
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200143static int do_lcd_clear(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100144{
145 *LCD_CMD_ADDR = 0x01;
146 mdelay(LCD_DELAY_NORMAL_MS);
147 return 0;
148}
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200149static int do_lcd_puts(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100150{
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200151 if (argc < 2)
152 return cmd_usage(cmdtp);
153
Stefan Roese5fb692c2007-01-18 10:25:34 +0100154 lcd_puts(argv[1]);
155 return 0;
156}
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200157static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100158{
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200159 if (argc < 2)
160 return cmd_usage(cmdtp);
161
Stefan Roese5fb692c2007-01-18 10:25:34 +0100162 lcd_putc((char)argv[1][0]);
163 return 0;
164}
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200165static int do_lcd_cur(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100166{
167 ulong count;
168 ulong dir;
169 char cur_addr;
170
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200171 if (argc < 3)
172 return cmd_usage(cmdtp);
Stefan Roese5fb692c2007-01-18 10:25:34 +0100173
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
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200235U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd test display", "");
236U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd clear display", "");
Stefan Roese5fb692c2007-01-18 10:25:34 +0100237U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts,
Peter Tyser2fb26042009-01-27 18:03:12 -0600238 "display string on lcd",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200239 "<string> - <string> to be displayed");
Stefan Roese5fb692c2007-01-18 10:25:34 +0100240U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc,
Peter Tyser2fb26042009-01-27 18:03:12 -0600241 "display char on lcd",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200242 "<char> - <char> to be displayed");
Stefan Roese5fb692c2007-01-18 10:25:34 +0100243U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur,
Peter Tyser2fb26042009-01-27 18:03:12 -0600244 "shift cursor on lcd",
Stefan Roese5fb692c2007-01-18 10:25:34 +0100245 "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200246 " <count> - 0~31\n" " <dir> - 0,backward; 1, forward");
Stefan Roese5fb692c2007-01-18 10:25:34 +0100247
Wolfgang Denka4012392007-01-19 23:08:39 +0100248#if 0 /* test-only */
Stefan Roese5fb692c2007-01-18 10:25:34 +0100249void 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);
Wolfgang Denka4012392007-01-19 23:08:39 +0100299#endif /* 0 */
Stefan Roese5fb692c2007-01-18 10:25:34 +0100300}
301
302void 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}
Wolfgang Denka4012392007-01-19 23:08:39 +0100335#endif /* 0 - test only */
Stefan Roese5fb692c2007-01-18 10:25:34 +0100336
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200337static int do_led_test_off(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100338{
339 volatile unsigned int *GpioOr =
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200340 (volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
Stefan Roese5fb692c2007-01-18 10:25:34 +0100341 *GpioOr |= 0x00300000;
342 return 0;
343}
344
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200345static int do_led_test_on(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
Stefan Roese5fb692c2007-01-18 10:25:34 +0100346{
347 volatile unsigned int *GpioOr =
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200348 (volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
Stefan Roese5fb692c2007-01-18 10:25:34 +0100349 *GpioOr &= ~0x00300000;
350 return 0;
351}
352
353U_BOOT_CMD(ledon, 1, 1, do_led_test_on,
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200354 "led test light on", "");
Stefan Roese5fb692c2007-01-18 10:25:34 +0100355
356U_BOOT_CMD(ledoff, 1, 1, do_led_test_off,
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200357 "led test light off", "");
Stefan Roese5fb692c2007-01-18 10:25:34 +0100358#endif