uboot/board/amcc/taishan/lcd.c
<<
>>
Prefs
   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
  40static int g_lcd_init_b = 0;
  41static char *amcc_logo = "  AMCC TAISHAN  440GX EvalBoard";
  42static char addr_flag = 0x80;
  43
  44static 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
  52static 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
  82static 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
 104static 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
 127int 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
 155static int do_lcd_test(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 156{
 157        lcd_init();
 158        return 0;
 159}
 160
 161static 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}
 167static int do_lcd_puts(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 168{
 169        if (argc < 2) {
 170                cmd_usage(cmdtp);
 171                return 1;
 172        }
 173        lcd_puts(argv[1]);
 174        return 0;
 175}
 176static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 177{
 178        if (argc < 2) {
 179                cmd_usage(cmdtp);
 180                return 1;
 181        }
 182        lcd_putc((char)argv[1][0]);
 183        return 0;
 184}
 185static 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                cmd_usage(cmdtp);
 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
 257U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd test display", "");
 258U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd clear display", "");
 259U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts,
 260           "display string on lcd",
 261           "<string> - <string> to be displayed");
 262U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc,
 263           "display char on lcd",
 264           "<char> - <char> to be displayed");
 265U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur,
 266           "shift cursor on lcd",
 267           "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n"
 268           " <count> - 0~31\n" " <dir> - 0,backward; 1, forward");
 269
 270#if 0 /* test-only */
 271void 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
 324void 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
 359static 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 *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
 363        *GpioOr |= 0x00300000;
 364        return 0;
 365}
 366
 367static 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 *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
 371        *GpioOr &= ~0x00300000;
 372        return 0;
 373}
 374
 375U_BOOT_CMD(ledon, 1, 1, do_led_test_on,
 376           "led test light on", "");
 377
 378U_BOOT_CMD(ledoff, 1, 1, do_led_test_off,
 379           "led test light off", "");
 380#endif
 381