3 * Copyright (C) 2012 Lothar Waßmann <LW@KARO-electronics.de>
6 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
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 version 2.
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
25 #include <fdt_support.h>
28 #include <linux/mtd/nand.h>
30 #include <asm/cache.h>
31 #include <asm/omap_common.h>
33 #include <asm/arch/cpu.h>
34 #include <asm/arch/hardware.h>
35 #include <asm/arch/mmc_host_def.h>
36 #include <asm/arch/sys_proto.h>
37 #include <asm/arch/nand.h>
38 #include <asm/arch/clock.h>
39 #include <asm/arch/common_def.h>
41 #include <asm/arch/da8xx-fb.h>
43 DECLARE_GLOBAL_DATA_PTR;
45 #define TX48_LED_GPIO AM33XX_GPIO_NR(1, 26)
46 #define TX48_ETH_PHY_RST_GPIO AM33XX_GPIO_NR(3, 8)
47 #define TX48_LCD_RST_GPIO AM33XX_GPIO_NR(1, 19)
48 #define TX48_LCD_PWR_GPIO AM33XX_GPIO_NR(1, 22)
49 #define TX48_LCD_BACKLIGHT_GPIO AM33XX_GPIO_NR(3, 14)
51 #define GMII_SEL (CTRL_BASE + 0x650)
54 #define UART_SYSCFG_OFFSET 0x54
55 #define UART_SYSSTS_OFFSET 0x58
57 #define UART_RESET (0x1 << 1)
58 #define UART_CLK_RUNNING_MASK 0x1
59 #define UART_SMART_IDLE_EN (0x1 << 0x3)
62 #define TSICR_REG 0x54
63 #define TIOCP_CFG_REG 0x10
66 /* RGMII mode define */
67 #define RGMII_MODE_ENABLE 0xA
68 #define RMII_MODE_ENABLE 0x5
69 #define MII_MODE_ENABLE 0x0
71 #define NO_OF_MAC_ADDR 1
74 #define MUX_CFG(value, offset) { \
75 __raw_writel(value, (CTRL_BASE + (offset))); \
78 /* PAD Control Fields */
79 #define SLEWCTRL (0x1 << 6)
80 #define RXACTIVE (0x1 << 5)
81 #define PULLUP_EN (0x1 << 4) /* Pull UP Selection */
82 #define PULLUDEN (0x0 << 3) /* Pull up enabled */
83 #define PULLUDDIS (0x1 << 3) /* Pull up disabled */
84 #define MODE(val) (val)
88 * Field names corresponds to the pad signal name
180 int ecap0_in_pwm0_out;
199 int xdma_event_intr0;
200 int xdma_event_intr1;
304 #define PAD_CTRL_BASE 0x800
305 #define OFFSET(x) (unsigned int) (&((struct pad_signals *) \
308 * Configure the pin mux for the module
310 static void tx48_set_pin_mux(const struct pin_mux *pin_mux,
315 for (i = 0; i < num_pins; i++)
316 MUX_CFG(pin_mux[i].val, pin_mux[i].reg_offset);
319 #define PRM_RSTST_GLOBAL_COLD_RST (1 << 0)
320 #define PRM_RSTST_GLOBAL_WARM_SW_RST (1 << 1)
321 #define PRM_RSTST_WDT1_RST (1 << 4)
322 #define PRM_RSTST_EXTERNAL_WARM_RST (1 << 5)
323 #define PRM_RSTST_ICEPICK_RST (1 << 9)
326 unsigned int prmrstctrl; /* offset 0x00 */
327 unsigned int prmrsttime; /* offset 0x04 */
328 unsigned int prmrstst; /* offset 0x08 */
333 * Basic board specific setup
335 static const struct pin_mux stk5_pads[] = {
337 { OFFSET(gpmc_a10), MODE(7) | PULLUDEN, },
339 { OFFSET(gpmc_a3), MODE(7) | PULLUDEN, },
340 /* LCD POWER_ENABLE */
341 { OFFSET(gpmc_a6), MODE(7) | PULLUDEN, },
342 /* LCD Backlight (PWM) */
343 { OFFSET(mcasp0_aclkx), MODE(7) | PULLUDEN, },
346 static const struct pin_mux stk5_lcd_pads[] = {
348 { OFFSET(lcd_data0), MODE(0) | PULLUDEN, },
349 { OFFSET(lcd_data1), MODE(0) | PULLUDEN, },
350 { OFFSET(lcd_data2), MODE(0) | PULLUDEN, },
351 { OFFSET(lcd_data3), MODE(0) | PULLUDEN, },
352 { OFFSET(lcd_data4), MODE(0) | PULLUDEN, },
353 { OFFSET(lcd_data5), MODE(0) | PULLUDEN, },
354 { OFFSET(lcd_data6), MODE(0) | PULLUDEN, },
355 { OFFSET(lcd_data7), MODE(0) | PULLUDEN, },
356 { OFFSET(lcd_data8), MODE(0) | PULLUDEN, },
357 { OFFSET(lcd_data9), MODE(0) | PULLUDEN, },
358 { OFFSET(lcd_data10), MODE(0) | PULLUDEN, },
359 { OFFSET(lcd_data11), MODE(0) | PULLUDEN, },
360 { OFFSET(lcd_data12), MODE(0) | PULLUDEN, },
361 { OFFSET(lcd_data13), MODE(0) | PULLUDEN, },
362 { OFFSET(lcd_data14), MODE(0) | PULLUDEN, },
363 { OFFSET(lcd_data15), MODE(0) | PULLUDEN, },
364 /* LCD control signals */
365 { OFFSET(lcd_hsync), MODE(0) | PULLUDEN, },
366 { OFFSET(lcd_vsync), MODE(0) | PULLUDEN, },
367 { OFFSET(lcd_pclk), MODE(0) | PULLUDEN, },
368 { OFFSET(lcd_ac_bias_en), MODE(0) | PULLUDEN, },
371 static const struct gpio stk5_gpios[] = {
372 { AM33XX_GPIO_NR(1, 26), GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
375 static const struct gpio stk5_lcd_gpios[] = {
376 { AM33XX_GPIO_NR(1, 19), GPIOF_OUTPUT_INIT_HIGH, "LCD RESET", },
377 { AM33XX_GPIO_NR(1, 22), GPIOF_OUTPUT_INIT_HIGH, "LCD POWER", },
378 { AM33XX_GPIO_NR(3, 14), GPIOF_OUTPUT_INIT_LOW, "LCD BACKLIGHT", },
381 static const struct gpio stk5_no_lcd_gpios[] = {
382 { AM33XX_GPIO_NR(1, 19), GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
383 { AM33XX_GPIO_NR(1, 22), GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
384 { AM33XX_GPIO_NR(3, 14), GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
387 static const struct pin_mux stk5v5_pads[] = {
388 /* CAN transceiver control */
389 { OFFSET(gpmc_ad8), MODE(7) | PULLUDEN, },
392 static const struct gpio stk5v5_gpios[] = {
393 { AM33XX_GPIO_NR(0, 22), GPIOF_OUTPUT_INIT_HIGH, "CAN XCVR", },
396 static u32 prm_rstst __attribute__((section(".data")));
399 static u16 tx48_cmap[256];
400 vidinfo_t panel_info = {
401 /* set to max. size supported by SoC */
405 .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
409 static struct da8xx_panel tx48_lcd_panel = {
410 .name = "640x480MR@60",
423 void *lcd_base; /* Start of framebuffer memory */
424 void *lcd_console_address; /* Start of console buffer */
433 void lcd_initcolregs(void)
437 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
441 void lcd_enable(void)
444 * global variable from common/lcd.c
445 * Set to 0 here to prevent messages from going to LCD
446 * rather than serial console
451 void lcd_disable(void)
455 void lcd_panel_disable(void)
459 static int lcd_enabled = 1;
461 static inline int tx48_load_splashimage(void)
464 #if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
465 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]);
466 cmd_tbl_t *cmd = find_cmd("nand");
467 char *loadaddr = getenv("splashimage");
474 const int argc = ARRAY_SIZE(argv);
480 if (tstc() || (prm_rstst & PRM_RSTST_WDT1_RST)) {
487 la = simple_strtoul(loadaddr, NULL, 16);
491 /* clear BMP header in memory */
492 memset((void *)la, 0, 64);
494 ret = do_nand(cmd, 0, argc, argv);
496 printf("Failed to load logo: %d\n", ret);
503 void lcd_ctrl_init(void *lcdbase)
505 int color_depth = 24;
508 struct da8xx_panel *p = &tx48_lcd_panel;
512 printf("LCD disabled\n");
516 if (tstc() || (prm_rstst & PRM_RSTST_WDT1_RST)) {
521 vm = getenv("video_mode");
527 strncpy((char *)p->name, vm, sizeof(p->name));
529 val = simple_strtoul(vm, &vm, 0);
531 if (val > panel_info.vl_col)
532 val = panel_info.vl_col;
534 panel_info.vl_col = val;
537 val = simple_strtoul(vm + 1, &vm, 0);
538 if (val > panel_info.vl_row)
539 val = panel_info.vl_row;
541 panel_info.vl_row = val;
543 while (*vm != '\0') {
551 color_depth = simple_strtoul(vm + 1, &vm, 10);
555 refresh = simple_strtoul(vm + 1, &vm, 10);
559 debug("Ignoring '%c'\n", *vm);
563 switch (color_depth) {
565 panel_info.vl_bpix = 3;
569 panel_info.vl_bpix = 4;
573 panel_info.vl_bpix = 5;
577 printf("Invalid color_depth %u from video_mode '%s'; using default: %u\n",
578 color_depth, getenv("video_mode"), 24);
580 lcd_line_length = NBITS(panel_info.vl_bpix) / 8 * panel_info.vl_col;
581 p->pxl_clk = refresh *
582 (p->width + p->hfp + p->hbp + p->hsw) *
583 (p->height + p->vfp + p->vbp + p->vsw);
584 debug("Pixel clock set to %u.%03uMHz\n",
585 p->pxl_clk / 1000000, p->pxl_clk / 1000 % 1000);
587 tx48_set_pin_mux(stk5_lcd_pads, ARRAY_SIZE(stk5_lcd_pads));
588 debug("Initializing FB driver\n");
589 da8xx_video_init(&tx48_lcd_panel, color_depth);
591 if (tx48_load_splashimage() == 0) {
592 debug("Initializing LCD controller\n");
595 debug("Skipping initialization of LCD controller\n");
599 ulong calc_fbsize(void)
601 return panel_info.vl_row * panel_info.vl_col * 2 *
602 NBITS(panel_info.vl_bpix) / 8;
605 #define lcd_enabled 0
606 #endif /* CONFIG_LCD */
608 static void stk5_board_init(void)
610 tx48_set_pin_mux(stk5_pads, ARRAY_SIZE(stk5_pads));
613 tx48_set_pin_mux(stk5_lcd_pads, ARRAY_SIZE(stk5_lcd_pads));
615 gpio_request_array(stk5_no_lcd_gpios,
616 ARRAY_SIZE(stk5_no_lcd_gpios));
619 static void stk5v3_board_init(void)
624 static void stk5v5_board_init(void)
627 tx48_set_pin_mux(stk5v5_pads, ARRAY_SIZE(stk5v5_pads));
628 gpio_request_array(stk5v5_gpios, ARRAY_SIZE(stk5v5_gpios));
631 /* called with default environment! */
634 /* mach type passed to kernel */
635 #ifdef CONFIG_OF_LIBFDT
636 gd->bd->bi_arch_number = -1;
638 /* address of boot parameters */
639 gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
644 static void show_reset_cause(u32 prm_rstst)
646 const char *dlm = "";
648 printf("RESET cause: ");
649 if (prm_rstst & PRM_RSTST_GLOBAL_COLD_RST) {
650 printf("%sPOR", dlm);
653 if (prm_rstst & PRM_RSTST_GLOBAL_WARM_SW_RST) {
657 if (prm_rstst & PRM_RSTST_WDT1_RST) {
658 printf("%sWATCHDOG", dlm);
661 if (prm_rstst & PRM_RSTST_EXTERNAL_WARM_RST) {
662 printf("%sWARM", dlm);
665 if (prm_rstst & PRM_RSTST_ICEPICK_RST) {
666 printf("%sJTAG", dlm);
675 #ifdef CONFIG_OF_LIBFDT
676 /* called with default environment! */
677 static void tx48_move_fdt(void)
679 unsigned long fdt_addr = getenv_ulong("fdtcontroladdr", 16, 0);
682 #ifdef CONFIG_OF_EMBED
683 fdt = _binary_dt_dtb_start;
684 #elif defined CONFIG_OF_SEPARATE
685 fdt = (void *)(_end_ofs + _TEXT_BASE);
687 if (fdt && fdt_addr != 0) {
688 if (fdt_check_header(fdt) == 0) {
689 size_t fdt_len = fdt_totalsize(fdt);
691 memmove((void *)fdt_addr, fdt, fdt_len);
693 printf("ERROR: No valid FDT found at %p\n", fdt);
699 /* called with default environment! */
702 struct prm_device *prmdev = (struct prm_device *)PRM_DEVICE;
704 prm_rstst = readl(&prmdev->prmrstst);
705 show_reset_cause(prm_rstst);
707 #ifdef CONFIG_OF_LIBFDT
708 printf("Board: Ka-Ro TX48-7020 with FDT support\n");
711 printf("Board: Ka-Ro TX48-7020\n");
716 unsigned long start = get_timer(0);
717 unsigned long last = gd->tbl;
718 unsigned long loop = 0;
719 unsigned long cnt = 0;
720 struct gptimer *timer_base = (struct gptimer *)CONFIG_SYS_TIMERBASE;
722 printf("clock tick rate: %lu.%03lukHz\n",
723 gd->timer_rate_hz / 1000, gd->timer_rate_hz % 1000);
724 printf("ticks/us=%lu\n", gd->timer_rate_hz / CONFIG_SYS_HZ / 1000);
727 unsigned long elapsed = get_timer(start);
728 unsigned long diff = gd->tbl - last;
733 printf("loop %4lu: t=%08lx diff=%08lx steps=%5lu elapsed time: %4lu",
734 loop, gd->tbl, diff, cnt, elapsed / CONFIG_SYS_HZ);
736 while (get_timer(elapsed + start) < CONFIG_SYS_HZ) {
740 printf(" tcrr=%08x\n", readl(&timer_base->tcrr));
747 /* called with environment from NAND or MMC */
748 int board_late_init(void)
750 const char *baseboard;
752 baseboard = getenv("baseboard");
756 if (strncmp(baseboard, "stk5", 4) == 0) {
757 printf("Baseboard: %s\n", baseboard);
758 if ((strlen(baseboard) == 4) ||
759 strcmp(baseboard, "stk5-v3") == 0) {
761 } else if (strcmp(baseboard, "stk5-v5") == 0) {
764 printf("WARNING: Unsupported STK5 board rev.: %s\n",
768 printf("WARNING: Unsupported baseboard: '%s'\n",
774 gpio_set_value(TX48_LCD_PWR_GPIO, 1);
775 gpio_set_value(TX48_LCD_RST_GPIO, 1);
777 gpio_set_value(TX48_LCD_BACKLIGHT_GPIO, 0);
782 #ifdef CONFIG_DRIVER_TI_CPSW
783 static void tx48_phy_init(char *name, int addr)
785 debug("%s: Resetting ethernet PHY\n", __func__);
787 gpio_direction_output(TX48_ETH_PHY_RST_GPIO, 0);
792 gpio_set_value(TX48_ETH_PHY_RST_GPIO, 1);
795 static void cpsw_control(int enabled)
797 /* nothing for now */
798 /* TODO : VTP was here before */
801 static struct cpsw_slave_data cpsw_slaves[] = {
803 .slave_reg_ofs = 0x208,
804 .sliver_reg_ofs = 0xd80,
809 static struct cpsw_platform_data cpsw_data = {
810 .mdio_base = CPSW_MDIO_BASE,
811 .cpsw_base = CPSW_BASE,
814 .cpdma_reg_ofs = 0x800,
815 .slaves = ARRAY_SIZE(cpsw_slaves),
816 .slave_data = cpsw_slaves,
817 .ale_reg_ofs = 0xd00,
819 .host_port_reg_ofs = 0x108,
820 .hw_stats_reg_ofs = 0x900,
821 .mac_control = (1 << 5) /* MIIEN */,
822 .control = cpsw_control,
823 .phy_init = tx48_phy_init,
826 .version = CPSW_CTRL_VERSION_2,
829 int board_eth_init(bd_t *bis)
831 uint8_t mac_addr[ETH_ALEN];
832 uint32_t mac_hi, mac_lo;
834 /* try reading mac address from efuse */
835 mac_lo = __raw_readl(MAC_ID0_LO);
836 mac_hi = __raw_readl(MAC_ID0_HI);
838 mac_addr[0] = mac_hi & 0xFF;
839 mac_addr[1] = (mac_hi & 0xFF00) >> 8;
840 mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
841 mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
842 mac_addr[4] = mac_lo & 0xFF;
843 mac_addr[5] = (mac_lo & 0xFF00) >> 8;
845 if (is_valid_ether_addr(mac_addr)) {
846 debug("MAC addr set to: %02x:%02x:%02x:%02x:%02x:%02x\n",
847 mac_addr[0], mac_addr[1], mac_addr[2],
848 mac_addr[3], mac_addr[4], mac_addr[5]);
849 eth_setenv_enetaddr("ethaddr", mac_addr);
851 printf("ERROR: Did not find a valid mac address in e-fuse\n");
854 __raw_writel(RMII_MODE_ENABLE, MAC_MII_SEL);
855 __raw_writel(0x5D, GMII_SEL);
856 return cpsw_register(&cpsw_data);
858 #endif /* CONFIG_DRIVER_TI_CPSW */
860 #ifndef CONFIG_SPL_BUILD
861 #ifdef CONFIG_NAND_AM33XX
862 /******************************************************************************
863 * Command to switch between NAND HW and SW ecc
864 *****************************************************************************/
865 static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
872 if (strncmp(argv[1], "hw", 2) == 0) {
874 type = simple_strtoul(argv[2], NULL, 10);
875 am33xx_nand_switch_ecc(NAND_ECC_HW, type);
877 else if (strncmp(argv[1], "sw", 2) == 0)
878 am33xx_nand_switch_ecc(NAND_ECC_SOFT, 0);
885 printf("Usage: nandecc %s\n", cmdtp->usage);
890 nandecc, 3, 1, do_switch_ecc,
891 "Switch NAND ECC calculation algorithm b/w hardware and software",
892 "[sw|hw <hw_type>] \n"
893 " [sw|hw]- Switch b/w hardware(hw) & software(sw) ecc algorithm\n"
894 " hw_type- 0 for Hamming code\n"
900 #endif /* CONFIG_NAND_AM33XX */
901 #endif /* CONFIG_SPL_BUILD */
909 void show_activity(int arg)
911 static int led_state = LED_STATE_INIT;
914 if (led_state == LED_STATE_INIT) {
916 gpio_set_value(TX48_LED_GPIO, 1);
917 led_state = LED_STATE_ON;
919 if (get_timer(last) > CONFIG_SYS_HZ) {
921 if (led_state == LED_STATE_ON) {
922 gpio_set_value(TX48_LED_GPIO, 0);
924 gpio_set_value(TX48_LED_GPIO, 1);
926 led_state = 1 - led_state;
931 #ifdef CONFIG_OF_BOARD_SETUP
932 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
933 #include <jffs2/jffs2.h>
934 #include <mtd_node.h>
935 struct node_info nodes[] = {
936 { "ti,omap2-nand", MTD_DEV_TYPE_NAND, },
940 #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
941 #endif /* CONFIG_FDT_FIXUP_PARTITIONS */
943 static const char *tx48_touchpanels[] = {
948 static void tx48_fixup_touchpanel(void *blob)
951 const char *model = getenv("touchpanel");
953 for (i = 0; i < ARRAY_SIZE(tx48_touchpanels); i++) {
955 const char *tp = tx48_touchpanels[i];
957 if (model != NULL && strcmp(model, tp) == 0)
960 tp = strchr(tp, ',');
961 if (tp != NULL && *tp != '\0' && strcmp(model, tp + 1) == 0)
964 offs = fdt_node_offset_by_compatible(blob, -1,
965 tx48_touchpanels[i]);
967 debug("node '%s' not found: %d\n",
968 tx48_touchpanels[i], offs);
971 debug("Removing node '%s' at offset %d\n",
972 tx48_touchpanels[i], offs);
973 fdt_del_node(blob, offs);
977 void ft_board_setup(void *blob, bd_t *bd)
979 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
980 fdt_fixup_ethernet(blob);
982 tx48_fixup_touchpanel(blob);
984 #endif /* CONFIG_OF_BOARD_SETUP */