#include <asm/gpio.h>
#include <asm/arch/iomux-mx53.h>
#include <asm/arch/clock.h>
+#include <asm/arch/hab.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/sys_proto.h>
#define TX53_SDHC_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_HYS | PAD_CTL_DSE_HIGH | \
PAD_CTL_SRE_FAST | PAD_CTL_PUS_47K_UP)
+char __uboot_img_end[0] __attribute__((section(".__uboot_img_end")));
+char __csf_data[0] __attribute__((section(".__csf_data")));
+
static iomux_v3_cfg_t tx53_pads[] = {
/* NAND flash pads are set up in lowlevel_init.S */
};
static const struct gpio tx53_gpios[] = {
- { TX53_RESET_OUT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "#RESET_OUT", },
- { TX53_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_HIGH, "FEC PHY PWR", },
- { TX53_FEC_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC PHY RESET", },
- { TX53_FEC_INT_GPIO, GPIOF_INPUT, "FEC PHY INT", },
+ { TX53_RESET_OUT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "#RESET_OUT", },
+ { TX53_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY PWR", },
+ { TX53_FEC_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY RESET", },
+ { TX53_FEC_INT_GPIO, GPIOFLAG_INPUT, "FEC PHY INT", },
};
/*
printf("\n");
}
+#define pr_lpgr_val(v, n, b, c) do { \
+ u32 __v = ((v) >> (b)) & ((1 << (c)) - 1); \
+ if (__v) \
+ printf(" %s=%0*x", #n, DIV_ROUND_UP(c, 4), __v); \
+} while (0)
+
+static inline void print_lpgr(u32 lpgr)
+{
+ if (!lpgr)
+ return;
+
+ printf("LPGR=%08x:", lpgr);
+ pr_lpgr_val(lpgr, SW_ISO, 31, 1);
+ pr_lpgr_val(lpgr, SECONDARY_BOOT, 30, 1);
+ pr_lpgr_val(lpgr, BLOCK_REWRITE, 29, 1);
+ pr_lpgr_val(lpgr, WDOG_BOOT, 28, 1);
+ pr_lpgr_val(lpgr, SBMR_SHADOW, 0, 26);
+ printf("\n");
+}
+
static void tx53_print_cpuinfo(void)
{
u32 cpurev;
+ struct srtc_regs *srtc_regs = (void *)SRTC_BASE_ADDR;
+ u32 lpgr = readl(&srtc_regs->lpgr);
cpurev = get_cpu_rev();
mxc_get_clock(MXC_ARM_CLK) / 1000000);
print_reset_cause();
+
+ print_lpgr(lpgr);
+
+ if (lpgr & (1 << 30))
+ printf("WARNING: U-Boot started from secondary bootstrap image\n");
+
+ if (lpgr) {
+ struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR;
+ u32 ccgr4 = readl(&ccm_regs->CCGR4);
+
+ writel(ccgr4 | MXC_CCM_CCGR4_SRTC(3), &ccm_regs->CCGR4);
+ writel(0, &srtc_regs->lpgr);
+ writel(ccgr4, &ccm_regs->CCGR4);
+ }
}
enum LTC3589_REGS {
LTC3589_SCR1 = 0x07,
+ LTC3589_SCR2 = 0x12,
+ LTC3589_VCCR = 0x20,
LTC3589_CLIRQ = 0x21,
LTC3589_B1DTV1 = 0x23,
LTC3589_B1DTV2 = 0x24,
LTC3589_L2DTV2 = 0x33,
};
-#define LTC3589_PGOOD_MASK (1 << 5)
+#define LTC3589_BnDTV1_PGOOD_MASK (1 << 5)
+#define LTC3589_BnDTV1_SLEW(n) (((n) & 3) << 6)
+
+#define LTC3589_CLK_RATE_LOW (1 << 5)
-#define LTC3589_CLK_RATE_LOW (1 << 5)
+#define LTC3589_SCR2_PGOOD_SHUTDWN (1 << 7)
#define VDD_LDO2_VAL mV_to_regval(vout_to_vref(1325 * 10, 2))
-#define VDD_CORE_VAL mV_to_regval(vout_to_vref(1240 * 10, 3))
+#define VDD_CORE_VAL mV_to_regval(vout_to_vref(1100 * 10, 3))
#define VDD_SOC_VAL mV_to_regval(vout_to_vref(1325 * 10, 4))
#define VDD_BUCK3_VAL mV_to_regval(vout_to_vref(2500 * 10, 5))
u8 val;
} ltc3589_regs[] = {
{ LTC3589_SCR1, 0x15, }, /* burst mode for all regulators except buck boost */
+ { LTC3589_SCR2, LTC3589_SCR2_PGOOD_SHUTDWN, }, /* enable shutdown on PGOOD Timeout */
- { LTC3589_L2DTV1, VDD_LDO2_VAL | LTC3589_PGOOD_MASK, },
+ { LTC3589_L2DTV1, VDD_LDO2_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
{ LTC3589_L2DTV2, VDD_LDO2_VAL | LTC3589_CLK_RATE_LOW, },
- { LTC3589_B1DTV1, VDD_CORE_VAL | LTC3589_PGOOD_MASK, },
+ { LTC3589_B1DTV1, VDD_CORE_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
{ LTC3589_B1DTV2, VDD_CORE_VAL, },
- { LTC3589_B2DTV1, VDD_SOC_VAL | LTC3589_PGOOD_MASK, },
+ { LTC3589_B2DTV1, VDD_SOC_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
{ LTC3589_B2DTV2, VDD_SOC_VAL, },
- { LTC3589_B3DTV1, VDD_BUCK3_VAL | LTC3589_PGOOD_MASK, },
+ { LTC3589_B3DTV1, VDD_BUCK3_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
{ LTC3589_B3DTV2, VDD_BUCK3_VAL, },
+ /* Select ref 0 for all regulators and enable slew */
+ { LTC3589_VCCR, 0x55, },
+
{ LTC3589_CLIRQ, 0, }, /* clear all interrupt flags */
};
return 0;
}
+static struct {
+ u32 max_freq;
+ u32 mV;
+} tx53_core_voltages[] = {
+ { 800000000, 1100, },
+ { 1000000000, 1240, },
+ { 1200000000, 1350, },
+};
+
+int adjust_core_voltage(u32 freq)
+{
+ int ret;
+ int i;
+
+ printf("%s@%d\n", __func__, __LINE__);
+
+ for (i = 0; i < ARRAY_SIZE(tx53_core_voltages); i++) {
+ if (freq <= tx53_core_voltages[i].max_freq) {
+ int retries = 0;
+ const int max_tries = 10;
+ const int delay_us = 1;
+ u32 mV = tx53_core_voltages[i].mV;
+ u8 val = mV_to_regval(vout_to_vref(mV * 10, 3));
+ u8 v;
+
+ debug("regval[%umV]=%02x\n", mV, val);
+
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE, LTC3589_B1DTV1, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, LTC3589_B1DTV1, ret);
+ return ret;
+ }
+ debug("Changing reg %02x from %02x to %02x\n",
+ LTC3589_B1DTV1, v, (v & ~0x1f) |
+ mV_to_regval(vout_to_vref(mV * 10, 3)));
+ v &= ~0x1f;
+ v |= mV_to_regval(vout_to_vref(mV * 10, 3));
+ ret = i2c_write(CONFIG_SYS_I2C_SLAVE, LTC3589_B1DTV1, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, LTC3589_B1DTV1, ret);
+ return ret;
+ }
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE, LTC3589_VCCR, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, LTC3589_VCCR, ret);
+ return ret;
+ }
+ v |= 0x1;
+ ret = i2c_write(CONFIG_SYS_I2C_SLAVE, LTC3589_VCCR, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, LTC3589_VCCR, ret);
+ return ret;
+ }
+ for (retries = 0; retries < max_tries; retries++) {
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE,
+ LTC3589_VCCR, 1, &v, 1);
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, LTC3589_VCCR, ret);
+ return ret;
+ }
+ if (!(v & 1))
+ break;
+ udelay(delay_us);
+ }
+ if (v & 1) {
+ printf("change of VDDCORE did not complete after %uµs\n",
+ retries * delay_us);
+ return -ETIMEDOUT;
+ }
+
+ printf("VDDCORE set to %umV after %u loops\n",
+ DIV_ROUND(vref_to_vout(regval_to_mV(val & 0x1f), 3),
+ 10), retries);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
int board_early_init_f(void)
{
struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR;
- gpio_request_array(tx53_gpios, ARRAY_SIZE(tx53_gpios));
- imx_iomux_v3_setup_multiple_pads(tx53_pads, ARRAY_SIZE(tx53_pads));
-
writel(0x77777777, AIPS1_BASE_ADDR + 0x00);
writel(0x77777777, AIPS1_BASE_ADDR + 0x04);
writel(0x00000000, AIPS2_BASE_ADDR + 0x50);
writel(0xffcf0fff, &ccm_regs->CCGR0);
- writel(0x000fffc3, &ccm_regs->CCGR1);
+ writel(0x000fffcf, &ccm_regs->CCGR1);
writel(0x033c0000, &ccm_regs->CCGR2);
writel(0x000000ff, &ccm_regs->CCGR3);
writel(0x00000000, &ccm_regs->CCGR4);
writel(0xfff00000, &ccm_regs->CCGR7);
writel(0x00000000, &ccm_regs->cmeor);
+ imx_iomux_v3_setup_multiple_pads(tx53_pads, ARRAY_SIZE(tx53_pads));
+
return 0;
}
{
int ret;
+ ret = gpio_request_array(tx53_gpios, ARRAY_SIZE(tx53_gpios));
+ if (ret < 0) {
+ printf("Failed to request tx53_gpios: %d\n", ret);
+ }
+
/* Address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000;
if (ctrlc() || (wrsr & WRSR_TOUT)) {
- printf("CTRL-C detected; Skipping PMIC setup\n");
- return 1;
+ if (wrsr & WRSR_TOUT)
+ printf("WDOG RESET detected; Skipping PMIC setup\n");
+ else
+ printf("<CTRL-C> detected; safeboot enabled\n");
+ return 0;
}
ret = setup_pmic_voltages();
{
int ret;
- /* dram_init must store complete ramsize in gd->ram_size */
- gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
- PHYS_SDRAM_1_SIZE);
+ /*
+ * U-Boot doesn't support RAM banks with intervening holes,
+ * so let U-Boot only know about the first bank for its
+ * internal data structures. The size reported to Linux is
+ * determined from the individual bank sizes.
+ */
+ gd->ram_size = get_ram_size((void *)PHYS_SDRAM_1, SZ_1G);
ret = mxc_set_clock(CONFIG_SYS_MX5_HCLK,
CONFIG_SYS_SDRAM_CLK, MXC_DDR_CLK);
void dram_init_banksize(void)
{
+ long total_size = gd->ram_size;
+
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = get_ram_size((void *)PHYS_SDRAM_1,
- PHYS_SDRAM_1_SIZE);
+ gd->bd->bi_dram[0].size = gd->ram_size;
+
#if CONFIG_NR_DRAM_BANKS > 1
- gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
- gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2,
- PHYS_SDRAM_2_SIZE);
+ gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2, SZ_1G);
+
+ if (gd->bd->bi_dram[1].size) {
+ debug("Found %luMiB SDRAM in bank 2\n",
+ gd->bd->bi_dram[1].size / SZ_1M);
+ gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+ total_size += gd->bd->bi_dram[1].size;
+ }
#endif
+ if (total_size != CONFIG_SYS_SDRAM_SIZE)
+ printf("WARNING: SDRAM size mismatch: %uMiB configured; %luMiB detected\n",
+ CONFIG_SYS_SDRAM_SIZE / SZ_1M, total_size / SZ_1M);
}
#ifdef CONFIG_CMD_MMC
cfg->cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
ret = gpio_request_one(cfg->cd_gpio,
- GPIOF_INPUT, "MMC CD");
+ GPIOFLAG_INPUT, "MMC CD");
if (ret) {
printf("Error %d requesting GPIO%d_%d\n",
ret, cfg->cd_gpio / 32, cfg->cd_gpio % 32);
};
static const struct gpio stk5_gpios[] = {
- { TX53_LED_GPIO, GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
+ { TX53_LED_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
- { IMX_GPIO_NR(1, 8), GPIOF_INPUT, "USBOTG OC", },
- { IMX_GPIO_NR(1, 7), GPIOF_OUTPUT_INIT_LOW, "USBOTG VBUS enable", },
- { IMX_GPIO_NR(3, 30), GPIOF_INPUT, "USBH1 OC", },
- { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
+ { IMX_GPIO_NR(1, 8), GPIOFLAG_INPUT, "USBOTG OC", },
+ { IMX_GPIO_NR(1, 7), GPIOFLAG_OUTPUT_INIT_LOW, "USBOTG VBUS enable", },
+ { IMX_GPIO_NR(3, 30), GPIOFLAG_INPUT, "USBH1 OC", },
+ { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
};
#ifdef CONFIG_LCD
-static u16 tx53_cmap[256];
vidinfo_t panel_info = {
/* set to max. size supported by SoC */
.vl_col = 1600,
.vl_row = 1200,
- .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
- .cmap = tx53_cmap,
+ .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
};
static struct fb_videomode tx53_fb_modes[] = {
.upper_margin = 2,
.vsync_len = 10,
.lower_margin = 2,
- .sync = FB_SYNC_CLK_LAT_FALL,
},
{
/* Emerging ET0500G0DH6 800 x 480 display.
};
static const struct gpio stk5_lcd_gpios[] = {
- { TX53_LCD_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
- { TX53_LCD_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
- { TX53_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ { TX53_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
+ { TX53_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
+ { TX53_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
};
void lcd_ctrl_init(void *lcdbase)
}
karo_fdt_move_fdt();
- lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
if (video_mode == NULL) {
debug("Disabling LCD\n");
lcd_enabled = 0;
return;
}
+
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
vm = video_mode;
if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
p = &fb_mode;
panel_info.vl_bpix = LCD_COLOR16;
break;
default:
- panel_info.vl_bpix = LCD_COLOR24;
+ panel_info.vl_bpix = LCD_COLOR32;
}
p->pixclock = KHZ2PICOS(refresh *
{
stk5_board_init();
- gpio_request_one(IMX_GPIO_NR(4, 21), GPIOF_OUTPUT_INIT_HIGH,
+ gpio_request_one(IMX_GPIO_NR(4, 21), GPIOFLAG_OUTPUT_INIT_HIGH,
"Flexcan Transceiver");
imx_iomux_v3_setup_pad(MX53_PAD_DISP0_DAT0__GPIO4_21);
}
{
unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
- if (had_ctrlc() || (wrsr & WRSR_TOUT))
+ if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000)
return;
- if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000)
+ if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
+ printf("%s detected; skipping cpu clock change\n",
+ (wrsr & WRSR_TOUT) ? "WDOG RESET" : "<CTRL-C>");
return;
+ }
if (mxc_set_clock(CONFIG_SYS_MX5_HCLK, cpu_clk, MXC_ARM_CLK) == 0) {
cpu_clk = mxc_get_clock(MXC_ARM_CLK);
u8 mac[ETH_ALEN];
imx_get_mac_from_fuse(0, mac);
- if (!is_valid_ether_addr(mac)) {
+ if (!is_valid_ethaddr(mac)) {
printf("No valid MAC address programmed\n");
return;
}
int board_late_init(void)
{
- int ret = 0;
const char *baseboard;
+ env_cleanup();
+
tx53_set_cpu_clock();
- karo_fdt_move_fdt();
+
+ if (had_ctrlc())
+ setenv_ulong("safeboot", 1);
+ else if (wrsr & WRSR_TOUT)
+ setenv_ulong("wdreset", 1);
+ else
+ karo_fdt_move_fdt();
baseboard = getenv("baseboard");
if (!baseboard)
} else {
printf("WARNING: Unsupported baseboard: '%s'\n",
baseboard);
- ret = -EINVAL;
+ if (!had_ctrlc())
+ return -EINVAL;
}
exit:
gpio_set_value(TX53_RESET_OUT_GPIO, 1);
clear_ctrlc();
- return ret;
+
+ get_hab_status();
+
+ return 0;
}
int checkboard(void)
{
tx53_print_cpuinfo();
-
- printf("Board: Ka-Ro TX53-x%d3%s\n",
- is_lvds(), TX53_MOD_SUFFIX);
-
+#if CONFIG_SYS_SDRAM_SIZE < SZ_1G
+ printf("Board: Ka-Ro TX53-8%d3%c\n",
+ is_lvds(), '0' + CONFIG_SYS_SDRAM_SIZE / SZ_1G);
+#elif CONFIG_SYS_SDRAM_SIZE < SZ_2G
+ printf("Board: Ka-Ro TX53-1%d3%c\n",
+ is_lvds() + 2, '0' + CONFIG_SYS_SDRAM_SIZE / SZ_1G);
+#else
+ printf("Board: Ka-Ro TX53-123%c\n",
+ '0' + CONFIG_SYS_SDRAM_SIZE / SZ_1G);
+#endif
return 0;
}
"eeti,egalax_ts",
};
-void ft_board_setup(void *blob, bd_t *bd)
+int ft_board_setup(void *blob, bd_t *bd)
{
const char *baseboard = getenv("baseboard");
int stk5_v5 = baseboard != NULL && (strcmp(baseboard, "stk5-v5") == 0);
int ret;
ret = fdt_increase_size(blob, 4096);
- if (ret)
+ if (ret) {
printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
+ return ret;
+ }
+ if (stk5_v5)
+ karo_fdt_enable_node(blob, "stk5led", 0);
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
- fdt_fixup_ethernet(blob);
karo_fdt_fixup_touchpanel(blob, tx53_touchpanels,
ARRAY_SIZE(tx53_touchpanels));
- karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy");
+ karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply");
karo_fdt_fixup_flexcan(blob, stk5_v5);
tx53_fixup_rtc(blob);
karo_fdt_update_fb_mode(blob, video_mode);
+
+ return 0;
}
#endif /* CONFIG_OF_BOARD_SETUP */