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>
40 #include <asm/arch/da8xx-fb.h>
42 #include "../common/karo.h"
44 DECLARE_GLOBAL_DATA_PTR;
46 #define TX48_LED_GPIO AM33XX_GPIO_NR(1, 26)
47 #define TX48_ETH_PHY_RST_GPIO AM33XX_GPIO_NR(3, 8)
48 #define TX48_LCD_RST_GPIO AM33XX_GPIO_NR(1, 19)
49 #define TX48_LCD_PWR_GPIO AM33XX_GPIO_NR(1, 22)
50 #define TX48_LCD_BACKLIGHT_GPIO AM33XX_GPIO_NR(3, 14)
52 #define GMII_SEL (CTRL_BASE + 0x650)
55 #define UART_SYSCFG_OFFSET 0x54
56 #define UART_SYSSTS_OFFSET 0x58
58 #define UART_RESET (0x1 << 1)
59 #define UART_CLK_RUNNING_MASK 0x1
60 #define UART_SMART_IDLE_EN (0x1 << 0x3)
63 #define TSICR_REG 0x54
64 #define TIOCP_CFG_REG 0x10
67 /* RGMII mode define */
68 #define RGMII_MODE_ENABLE 0xA
69 #define RMII_MODE_ENABLE 0x5
70 #define MII_MODE_ENABLE 0x0
72 #define NO_OF_MAC_ADDR 1
75 #define MUX_CFG(value, offset) { \
76 __raw_writel(value, (CTRL_BASE + (offset))); \
79 /* PAD Control Fields */
80 #define SLEWCTRL (0x1 << 6)
81 #define RXACTIVE (0x1 << 5)
82 #define PULLUP_EN (0x1 << 4) /* Pull UP Selection */
83 #define PULLUDEN (0x0 << 3) /* Pull up enabled */
84 #define PULLUDDIS (0x1 << 3) /* Pull up disabled */
85 #define MODE(val) (val)
89 * Field names corresponds to the pad signal name
181 int ecap0_in_pwm0_out;
200 int xdma_event_intr0;
201 int xdma_event_intr1;
305 #define PAD_CTRL_BASE 0x800
306 #define OFFSET(x) (unsigned int) (&((struct pad_signals *) \
310 * Configure the pin mux for the module
312 static inline void tx48_set_pin_mux(const struct pin_mux *pin_mux,
317 for (i = 0; i < num_pins; i++)
318 MUX_CFG(pin_mux[i].val, pin_mux[i].reg_offset);
321 #define PRM_RSTST_GLOBAL_COLD_RST (1 << 0)
322 #define PRM_RSTST_GLOBAL_WARM_SW_RST (1 << 1)
323 #define PRM_RSTST_WDT1_RST (1 << 4)
324 #define PRM_RSTST_EXTERNAL_WARM_RST (1 << 5)
325 #define PRM_RSTST_ICEPICK_RST (1 << 9)
327 static u32 prm_rstst __attribute__((section(".data")));
330 * Basic board specific setup
332 static const struct pin_mux stk5_pads[] = {
334 { OFFSET(gpmc_a10), MODE(7) | PULLUDEN, },
336 { OFFSET(gpmc_a3), MODE(7) | PULLUDEN, },
337 /* LCD POWER_ENABLE */
338 { OFFSET(gpmc_a6), MODE(7) | PULLUDEN, },
339 /* LCD Backlight (PWM) */
340 { OFFSET(mcasp0_aclkx), MODE(7) | PULLUDEN, },
343 static const struct pin_mux stk5_lcd_pads[] = {
345 { OFFSET(lcd_data0), MODE(0) | PULLUDEN, },
346 { OFFSET(lcd_data1), MODE(0) | PULLUDEN, },
347 { OFFSET(lcd_data2), MODE(0) | PULLUDEN, },
348 { OFFSET(lcd_data3), MODE(0) | PULLUDEN, },
349 { OFFSET(lcd_data4), MODE(0) | PULLUDEN, },
350 { OFFSET(lcd_data5), MODE(0) | PULLUDEN, },
351 { OFFSET(lcd_data6), MODE(0) | PULLUDEN, },
352 { OFFSET(lcd_data7), MODE(0) | PULLUDEN, },
353 { OFFSET(lcd_data8), MODE(0) | PULLUDEN, },
354 { OFFSET(lcd_data9), MODE(0) | PULLUDEN, },
355 { OFFSET(lcd_data10), MODE(0) | PULLUDEN, },
356 { OFFSET(lcd_data11), MODE(0) | PULLUDEN, },
357 { OFFSET(lcd_data12), MODE(0) | PULLUDEN, },
358 { OFFSET(lcd_data13), MODE(0) | PULLUDEN, },
359 { OFFSET(lcd_data14), MODE(0) | PULLUDEN, },
360 { OFFSET(lcd_data15), MODE(0) | PULLUDEN, },
361 /* LCD control signals */
362 { OFFSET(lcd_hsync), MODE(0) | PULLUDEN, },
363 { OFFSET(lcd_vsync), MODE(0) | PULLUDEN, },
364 { OFFSET(lcd_pclk), MODE(0) | PULLUDEN, },
365 { OFFSET(lcd_ac_bias_en), MODE(0) | PULLUDEN, },
368 static const struct gpio stk5_gpios[] = {
369 { AM33XX_GPIO_NR(1, 26), GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
372 static const struct gpio stk5_lcd_gpios[] = {
373 { AM33XX_GPIO_NR(1, 19), GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
374 { AM33XX_GPIO_NR(1, 22), GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
375 { AM33XX_GPIO_NR(3, 14), GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
378 static const struct pin_mux stk5v5_pads[] = {
379 /* CAN transceiver control */
380 { OFFSET(gpmc_ad8), MODE(7) | PULLUDEN, },
383 static const struct gpio stk5v5_gpios[] = {
384 { AM33XX_GPIO_NR(0, 22), GPIOF_OUTPUT_INIT_HIGH, "CAN XCVR", },
388 static u16 tx48_cmap[256];
389 vidinfo_t panel_info = {
390 /* set to max. size supported by SoC */
394 .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
398 static struct da8xx_panel tx48_lcd_panel = {
399 .name = "640x480MR@60",
412 void *lcd_base; /* Start of framebuffer memory */
413 void *lcd_console_address; /* Start of console buffer */
422 static int lcd_enabled = 1;
424 void lcd_initcolregs(void)
428 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
432 void lcd_enable(void)
435 * global variable from common/lcd.c
436 * Set to 0 here to prevent messages from going to LCD
437 * rather than serial console
442 karo_load_splashimage(1);
444 gpio_set_value(TX48_LCD_PWR_GPIO, 1);
445 gpio_set_value(TX48_LCD_RST_GPIO, 1);
447 gpio_set_value(TX48_LCD_BACKLIGHT_GPIO, 0);
451 void lcd_disable(void)
459 void lcd_panel_disable(void)
462 gpio_set_value(TX48_LCD_BACKLIGHT_GPIO, 1);
463 gpio_set_value(TX48_LCD_PWR_GPIO, 0);
464 gpio_set_value(TX48_LCD_RST_GPIO, 0);
468 void lcd_ctrl_init(void *lcdbase)
470 int color_depth = 24;
473 struct da8xx_panel *p = &tx48_lcd_panel;
477 printf("LCD disabled\n");
481 if (tstc() || (prm_rstst & PRM_RSTST_WDT1_RST)) {
486 vm = getenv("video_mode");
492 if ((v = strstr(vm, ":")))
495 strncpy((char *)p->name, vm, sizeof(p->name));
497 val = simple_strtoul(vm, &vm, 10);
499 if (val > panel_info.vl_col)
500 val = panel_info.vl_col;
502 panel_info.vl_col = val;
505 val = simple_strtoul(vm + 1, &vm, 10);
506 if (val > panel_info.vl_row)
507 val = panel_info.vl_row;
509 panel_info.vl_row = val;
511 while (*vm != '\0') {
519 color_depth = simple_strtoul(vm + 1, &vm, 10);
523 refresh = simple_strtoul(vm + 1, &vm, 10);
527 debug("Ignoring '%c'\n", *vm);
531 switch (color_depth) {
533 panel_info.vl_bpix = 3;
537 panel_info.vl_bpix = 4;
541 panel_info.vl_bpix = 5;
545 printf("Invalid color_depth %u from video_mode '%s'; using default: %u\n",
546 color_depth, getenv("video_mode"), 24);
548 lcd_line_length = NBITS(panel_info.vl_bpix) / 8 * panel_info.vl_col;
549 p->pxl_clk = refresh *
550 (p->width + p->hfp + p->hbp + p->hsw) *
551 (p->height + p->vfp + p->vbp + p->vsw);
552 debug("Pixel clock set to %u.%03uMHz\n",
553 p->pxl_clk / 1000000, p->pxl_clk / 1000 % 1000);
555 gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
556 tx48_set_pin_mux(stk5_lcd_pads, ARRAY_SIZE(stk5_lcd_pads));
557 debug("Initializing FB driver\n");
558 da8xx_video_init(&tx48_lcd_panel, color_depth);
560 if (karo_load_splashimage(0) == 0) {
561 debug("Initializing LCD controller\n");
564 debug("Skipping initialization of LCD controller\n");
568 #define lcd_enabled 0
569 #endif /* CONFIG_LCD */
571 static void stk5_board_init(void)
573 tx48_set_pin_mux(stk5_pads, ARRAY_SIZE(stk5_pads));
576 static void stk5v3_board_init(void)
581 static void stk5v5_board_init(void)
584 tx48_set_pin_mux(stk5v5_pads, ARRAY_SIZE(stk5v5_pads));
585 gpio_request_array(stk5v5_gpios, ARRAY_SIZE(stk5v5_gpios));
588 /* called with default environment! */
591 /* mach type passed to kernel */
592 #ifdef CONFIG_OF_LIBFDT
593 gd->bd->bi_arch_number = -1;
595 /* address of boot parameters */
596 gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
601 static void show_reset_cause(u32 prm_rstst)
603 const char *dlm = "";
605 printf("RESET cause: ");
606 if (prm_rstst & PRM_RSTST_GLOBAL_COLD_RST) {
607 printf("%sPOR", dlm);
610 if (prm_rstst & PRM_RSTST_GLOBAL_WARM_SW_RST) {
614 if (prm_rstst & PRM_RSTST_WDT1_RST) {
615 printf("%sWATCHDOG", dlm);
618 if (prm_rstst & PRM_RSTST_EXTERNAL_WARM_RST) {
619 printf("%sWARM", dlm);
622 if (prm_rstst & PRM_RSTST_ICEPICK_RST) {
623 printf("%sJTAG", dlm);
632 /* called with default environment! */
635 prm_rstst = readl(PRM_RSTST);
636 show_reset_cause(prm_rstst);
638 #ifdef CONFIG_OF_LIBFDT
639 printf("Board: Ka-Ro TX48-7020 with FDT support\n");
641 printf("Board: Ka-Ro TX48-7020\n");
647 static void tx48_set_cpu_clock(void)
649 unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
651 if (tstc() || (prm_rstst & PRM_RSTST_WDT1_RST))
654 if (cpu_clk == 0 || cpu_clk == mpu_clk_rate() / 1000000)
657 mpu_pll_config(cpu_clk);
659 printf("CPU clock set to %lu.%03lu MHz\n",
660 mpu_clk_rate() / 1000000,
661 mpu_clk_rate() / 1000 % 1000);
664 /* called with environment from NAND or MMC */
665 int board_late_init(void)
667 const char *baseboard;
669 tx48_set_cpu_clock();
670 #ifdef CONFIG_OF_BOARD_SETUP
673 baseboard = getenv("baseboard");
677 if (strncmp(baseboard, "stk5", 4) == 0) {
678 printf("Baseboard: %s\n", baseboard);
679 if ((strlen(baseboard) == 4) ||
680 strcmp(baseboard, "stk5-v3") == 0) {
682 } else if (strcmp(baseboard, "stk5-v5") == 0) {
685 printf("WARNING: Unsupported STK5 board rev.: %s\n",
689 printf("WARNING: Unsupported baseboard: '%s'\n",
697 #ifdef CONFIG_DRIVER_TI_CPSW
698 static void tx48_phy_init(char *name, int addr)
700 debug("%s: Resetting ethernet PHY\n", __func__);
702 gpio_direction_output(TX48_ETH_PHY_RST_GPIO, 0);
707 gpio_set_value(TX48_ETH_PHY_RST_GPIO, 1);
709 /* Wait for PHY internal POR signal to deassert */
713 static void cpsw_control(int enabled)
715 /* nothing for now */
716 /* TODO : VTP was here before */
719 static struct cpsw_slave_data cpsw_slaves[] = {
721 .slave_reg_ofs = 0x208,
722 .sliver_reg_ofs = 0xd80,
724 .phy_if = PHY_INTERFACE_MODE_RMII,
730 /* Nothing to be done here */
733 static struct cpsw_platform_data cpsw_data = {
734 .mdio_base = AM335X_CPSW_MDIO_BASE,
735 .cpsw_base = AM335X_CPSW_BASE,
738 .cpdma_reg_ofs = 0x800,
739 .slaves = ARRAY_SIZE(cpsw_slaves),
740 .slave_data = cpsw_slaves,
741 .ale_reg_ofs = 0xd00,
743 .host_port_reg_ofs = 0x108,
744 .hw_stats_reg_ofs = 0x900,
745 .mac_control = (1 << 5) /* MIIEN */,
746 .control = cpsw_control,
747 .phy_init = tx48_phy_init,
750 .version = CPSW_CTRL_VERSION_2,
753 int board_eth_init(bd_t *bis)
755 uint8_t mac_addr[ETH_ALEN];
756 uint32_t mac_hi, mac_lo;
758 /* try reading mac address from efuse */
759 mac_lo = __raw_readl(MAC_ID0_LO);
760 mac_hi = __raw_readl(MAC_ID0_HI);
762 mac_addr[0] = mac_hi & 0xFF;
763 mac_addr[1] = (mac_hi & 0xFF00) >> 8;
764 mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
765 mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
766 mac_addr[4] = mac_lo & 0xFF;
767 mac_addr[5] = (mac_lo & 0xFF00) >> 8;
769 if (is_valid_ether_addr(mac_addr)) {
770 debug("MAC addr set to: %pM\n", mac_addr);
771 eth_setenv_enetaddr("ethaddr", mac_addr);
773 printf("ERROR: Did not find a valid mac address in e-fuse\n");
776 __raw_writel(RMII_MODE_ENABLE, MAC_MII_SEL);
777 __raw_writel(0x5D, GMII_SEL);
778 return cpsw_register(&cpsw_data);
780 #endif /* CONFIG_DRIVER_TI_CPSW */
782 void tx48_disable_watchdog(void)
784 struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
786 while (readl(&wdtimer->wdtwwps) & (1 << 4))
788 writel(0xaaaa, &wdtimer->wdtwspr);
789 while (readl(&wdtimer->wdtwwps) & (1 << 4))
791 writel(0x5555, &wdtimer->wdtwspr);
794 #if defined(CONFIG_NAND_AM33XX) && defined(CONFIG_CMD_SWITCH_ECC)
795 /******************************************************************************
796 * Command to switch between NAND HW and SW ecc
797 *****************************************************************************/
798 static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
805 if (strncmp(argv[1], "hw", 2) == 0) {
807 type = simple_strtoul(argv[2], NULL, 10);
808 am33xx_nand_switch_ecc(NAND_ECC_HW, type);
810 else if (strncmp(argv[1], "sw", 2) == 0)
811 am33xx_nand_switch_ecc(NAND_ECC_SOFT, 0);
818 printf("Usage: nandecc %s\n", cmdtp->usage);
823 nandecc, 3, 1, do_switch_ecc,
824 "Switch NAND ECC calculation algorithm b/w hardware and software",
825 "[sw|hw <hw_type>] \n"
826 " [sw|hw]- Switch b/w hardware(hw) & software(sw) ecc algorithm\n"
827 " hw_type- 0 for Hamming code\n"
832 #endif /* CONFIG_NAND_AM33XX && CONFIG_CMD_SWITCH_ECC */
840 void show_activity(int arg)
842 static int led_state = LED_STATE_INIT;
845 if (led_state == LED_STATE_INIT) {
847 gpio_set_value(TX48_LED_GPIO, 1);
848 led_state = LED_STATE_ON;
850 if (get_timer(last) > CONFIG_SYS_HZ) {
852 if (led_state == LED_STATE_ON) {
853 gpio_set_value(TX48_LED_GPIO, 0);
855 gpio_set_value(TX48_LED_GPIO, 1);
857 led_state = 1 - led_state;
862 #ifdef CONFIG_OF_BOARD_SETUP
863 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
864 #include <jffs2/jffs2.h>
865 #include <mtd_node.h>
866 struct node_info nodes[] = {
867 { "ti,omap2-nand", MTD_DEV_TYPE_NAND, },
871 #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
872 #endif /* CONFIG_FDT_FIXUP_PARTITIONS */
874 static void tx48_fixup_flexcan(void *blob)
876 const char *baseboard = getenv("baseboard");
878 if (baseboard && strcmp(baseboard, "stk5-v5") == 0)
881 karo_fdt_del_prop(blob, "ti,dcan", 0x481cc000, "can-xcvr-enable");
882 karo_fdt_del_prop(blob, "ti,dcan", 0x481d0000, "can-xcvr-enable");
885 void ft_board_setup(void *blob, bd_t *bd)
887 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
888 fdt_fixup_ethernet(blob);
890 karo_fdt_fixup_touchpanel(blob);
891 tx48_fixup_flexcan(blob);
893 tx48_disable_watchdog();
895 #endif /* CONFIG_OF_BOARD_SETUP */