]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - board/karo/tx53/tx53.c
karo: tx53: don't print decimals for voltages
[karo-tx-uboot.git] / board / karo / tx53 / tx53.c
index 2684bd9611ce94ed55bbb3f1370319df5090881d..c80e7ebc3aac32506bc6e233561f0339c3a53a60 100644 (file)
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <i2c.h>
 #include <lcd.h>
 #include <netdev.h>
 #include <mmc.h>
@@ -186,6 +187,124 @@ static void tx53_print_cpuinfo(void)
        print_reset_cause();
 }
 
+enum LTC3589_REGS {
+       LTC3589_SCR1 = 0x07,
+       LTC3589_CLIRQ = 0x21,
+       LTC3589_B1DTV1 = 0x23,
+       LTC3589_B1DTV2 = 0x24,
+       LTC3589_VRRCR = 0x25,
+       LTC3589_B2DTV1 = 0x26,
+       LTC3589_B2DTV2 = 0x27,
+       LTC3589_B3DTV1 = 0x29,
+       LTC3589_B3DTV2 = 0x2a,
+       LTC3589_L2DTV1 = 0x32,
+       LTC3589_L2DTV2 = 0x33,
+};
+
+#define LTC3589_PGOOD_MASK     (1 << 5)
+
+#define LTC3589_CLK_RATE_LOW   (1 << 5)
+
+#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_SOC_VAL            mV_to_regval(vout_to_vref(1325 * 10, 4))
+#define VDD_BUCK3_VAL          mV_to_regval(vout_to_vref(2500 * 10, 5))
+
+#ifndef CONFIG_SYS_TX53_HWREV_2
+/* LDO2 vref divider */
+#define R1_2   180
+#define R2_2   191
+/* BUCK1 vref divider */
+#define R1_3   150
+#define R2_3   180
+/* BUCK2 vref divider */
+#define R1_4   180
+#define R2_4   191
+/* BUCK3 vref divider */
+#define R1_5   270
+#define R2_5   100
+#else
+/* no dividers on vref */
+#define R1_2   0
+#define R2_2   1
+#define R1_3   0
+#define R2_3   1
+#define R1_4   0
+#define R2_4   1
+#define R1_5   0
+#define R2_5   1
+#endif
+
+/* calculate voltages in 10mV */
+#define R1(idx)                        R1_##idx
+#define R2(idx)                        R2_##idx
+
+#define vout_to_vref(vout, idx)        ((vout) * R2(idx) / (R1(idx) + R2(idx)))
+#define vref_to_vout(vref, idx)        ((vref) * (R1(idx) + R2(idx)) / R2(idx))
+
+#define mV_to_regval(mV)       (((((mV) < 3625) ? 3625 : (mV)) - 3625) / 125)
+#define regval_to_mV(v)                (((v) * 125 + 3625))
+
+static struct pmic_regs {
+       enum LTC3589_REGS addr;
+       u8 val;
+} ltc3589_regs[] = {
+       { LTC3589_SCR1, 0x15, }, /* burst mode for all regulators */
+
+       { LTC3589_L2DTV1, VDD_LDO2_VAL | LTC3589_PGOOD_MASK, },
+       { LTC3589_L2DTV2, VDD_LDO2_VAL | LTC3589_CLK_RATE_LOW, },
+
+       { LTC3589_B1DTV1, VDD_CORE_VAL | LTC3589_PGOOD_MASK, },
+       { LTC3589_B1DTV2, VDD_CORE_VAL, },
+
+       { LTC3589_B2DTV1, VDD_SOC_VAL | LTC3589_PGOOD_MASK, },
+       { LTC3589_B2DTV2, VDD_SOC_VAL, },
+
+       { LTC3589_B3DTV1, VDD_BUCK3_VAL | LTC3589_PGOOD_MASK, },
+       { LTC3589_B3DTV2, VDD_BUCK3_VAL, },
+
+       { LTC3589_CLIRQ, 0, }, /* clear all interrupt flags */
+};
+
+static int setup_pmic_voltages(void)
+{
+       int ret;
+       unsigned char value;
+       int i;
+
+       ret = i2c_probe(CONFIG_SYS_I2C_SLAVE);
+       if (ret != 0) {
+               printf("Failed to initialize I2C\n");
+               return ret;
+       }
+
+       ret = i2c_read(CONFIG_SYS_I2C_SLAVE, 0x11, 1, &value, 1);
+       if (ret) {
+               printf("%s: i2c_read error: %d\n", __func__, ret);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(ltc3589_regs); i++) {
+               ret = i2c_read(CONFIG_SYS_I2C_SLAVE, ltc3589_regs[i].addr, 1,
+                               &value, 1);
+               debug("Writing %02x to reg %02x (%02x)\n",
+                       ltc3589_regs[i].val, ltc3589_regs[i].addr, value);
+               ret = i2c_write(CONFIG_SYS_I2C_SLAVE, ltc3589_regs[i].addr, 1,
+                               &ltc3589_regs[i].val, 1);
+               if (ret) {
+                       printf("%s: failed to write PMIC register %02x: %d\n",
+                               __func__, ltc3589_regs[i].addr, ret);
+                       return ret;
+               }
+       }
+       printf("VDDCORE set to %umV\n",
+               DIV_ROUND(vref_to_vout(regval_to_mV(VDD_CORE_VAL), 3), 10));
+
+       printf("VDDSOC  set to %umV\n",
+               DIV_ROUND(vref_to_vout(regval_to_mV(VDD_SOC_VAL), 4), 10));
+       return 0;
+}
+
 int board_early_init_f(void)
 {
        struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR;
@@ -226,8 +345,21 @@ int board_early_init_f(void)
 
 int board_init(void)
 {
+       int 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;
+       }
+
+       ret = setup_pmic_voltages();
+       if (ret) {
+               printf("Failed to setup PMIC voltages\n");
+               hang();
+       }
        return 0;
 }
 
@@ -392,7 +524,6 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 int board_eth_init(bd_t *bis)
 {
        int ret;
-       unsigned char mac[ETH_ALEN];
 
        /* delay at least 21ms for the PHY internal POR signal to deassert */
        udelay(22000);
@@ -401,15 +532,8 @@ int board_eth_init(bd_t *bis)
        gpio_set_value(TX53_FEC_RST_GPIO, 1);
 
        ret = cpu_eth_init(bis);
-       if (ret) {
+       if (ret)
                printf("cpu_eth_init() failed: %d\n", ret);
-               return ret;
-       }
-
-       imx_get_mac_from_fuse(0, mac);
-       eth_setenv_enetaddr("ethaddr", mac);
-       printf("MAC addr from fuse: %pM\n", mac);
-
        return ret;
 }
 #endif /* CONFIG_FEC_MXC */
@@ -720,7 +844,8 @@ static const struct gpio stk5_lcd_gpios[] = {
 void lcd_ctrl_init(void *lcdbase)
 {
        int color_depth = 24;
-       char *vm;
+       const char *video_mode = getenv("video_mode");
+       const char *vm;
        unsigned long val;
        int refresh = 60;
        struct fb_videomode *p = &tx53_fb_modes[0];
@@ -735,7 +860,7 @@ void lcd_ctrl_init(void *lcdbase)
                return;
        }
 
-       if (tstc() || (wrsr & WRSR_TOUT)) {
+       if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
                debug("Disabling LCD\n");
                lcd_enabled = 0;
                setenv("splashimage", NULL);
@@ -744,20 +869,25 @@ void lcd_ctrl_init(void *lcdbase)
 
        karo_fdt_move_fdt();
 
-       vm = getenv("video_mode");
+       vm = karo_fdt_set_display(video_mode, "/soc", "/soc/aips/ldb");
        if (vm == NULL) {
                debug("Disabling LCD\n");
                lcd_enabled = 0;
                return;
        }
+       video_mode = vm;
        if (karo_fdt_get_fb_mode(working_fdt, vm, &fb_mode) == 0) {
                p = &fb_mode;
                debug("Using video mode from FDT\n");
                vm += strlen(vm);
-               if (fb_mode.xres < panel_info.vl_col)
-                       panel_info.vl_col = fb_mode.xres;
-               if (fb_mode.yres < panel_info.vl_row)
-                       panel_info.vl_row = fb_mode.yres;
+               if (fb_mode.xres > panel_info.vl_col ||
+                       fb_mode.yres > panel_info.vl_row) {
+                       printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+                               fb_mode.xres, fb_mode.yres,
+                               panel_info.vl_col, panel_info.vl_row);
+                       lcd_enabled = 0;
+                       return;
+               }
        }
        if (p->name != NULL)
                debug("Trying compiled-in video modes\n");
@@ -862,6 +992,25 @@ void lcd_ctrl_init(void *lcdbase)
                printf("\n");
                return;
        }
+       if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
+               printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
+                       p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
+               lcd_enabled = 0;
+               return;
+       }
+       panel_info.vl_col = p->xres;
+       panel_info.vl_row = p->yres;
+
+       switch (color_depth) {
+       case 8:
+               panel_info.vl_bpix = LCD_COLOR8;
+               break;
+       case 16:
+               panel_info.vl_bpix = LCD_COLOR16;
+               break;
+       default:
+               panel_info.vl_bpix = LCD_COLOR24;
+       }
 
        p->pixclock = KHZ2PICOS(refresh *
                (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
@@ -873,14 +1022,13 @@ void lcd_ctrl_init(void *lcdbase)
 
        if (p != &fb_mode) {
                int ret;
-               char *modename = getenv("video_mode");
 
-               printf("Creating new display-timing node from '%s'\n",
-                       modename);
-               ret = karo_fdt_create_fb_mode(working_fdt, modename, p);
+               debug("Creating new display-timing node from '%s'\n",
+                       video_mode);
+               ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
                if (ret)
                        printf("Failed to create new display-timing node from '%s': %d\n",
-                               modename, ret);
+                               video_mode, ret);
        }
 
        gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
@@ -946,7 +1094,7 @@ static void tx53_set_cpu_clock(void)
        unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
        int ret;
 
-       if (tstc() || (wrsr & WRSR_TOUT))
+       if (had_ctrlc() || (wrsr & WRSR_TOUT))
                return;
 
        if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000)
@@ -962,6 +1110,20 @@ static void tx53_set_cpu_clock(void)
                mxc_get_clock(MXC_ARM_CLK) / 1000 % 1000);
 }
 
+static void tx53_init_mac(void)
+{
+       u8 mac[ETH_ALEN];
+
+       imx_get_mac_from_fuse(0, mac);
+       if (!is_valid_ether_addr(mac)) {
+               printf("No valid MAC address programmed\n");
+               return;
+       }
+
+       eth_setenv_enetaddr("ethaddr", mac);
+       printf("MAC addr from fuse: %pM\n", mac);
+}
+
 int board_late_init(void)
 {
        int ret = 0;
@@ -992,7 +1154,9 @@ int board_late_init(void)
        }
 
 exit:
+       tx53_init_mac();
        gpio_set_value(TX53_RESET_OUT_GPIO, 1);
+       clear_ctrlc();
        return ret;
 }
 
@@ -1018,17 +1182,6 @@ struct node_info nodes[] = {
 #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
 #endif
 
-static void tx53_fixup_flexcan(void *blob)
-{
-       const char *baseboard = getenv("baseboard");
-
-       if (baseboard && strcmp(baseboard, "stk5-v5") == 0)
-               return;
-
-       karo_fdt_del_prop(blob, "fsl,p1010-flexcan", 0x53fc8000, "transceiver-switch");
-       karo_fdt_del_prop(blob, "fsl,p1010-flexcan", 0x53fcc000, "transceiver-switch");
-}
-
 #ifdef CONFIG_SYS_TX53_HWREV_2
 void tx53_fixup_rtc(void *blob)
 {
@@ -1043,13 +1196,18 @@ static inline void tx53_fixup_rtc(void *blob)
 
 void ft_board_setup(void *blob, bd_t *bd)
 {
+       const char *baseboard = getenv("baseboard");
+       int stk5_v5 = baseboard != NULL && (strcmp(baseboard, "stk5-v5") == 0);
+       const char *video_mode = getenv("video_mode");
+
        fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
        fdt_fixup_ethernet(blob);
 
        karo_fdt_fixup_touchpanel(blob);
        karo_fdt_fixup_usb_otg(blob, "fsl,imx-otg", "fsl,usbphy");
-       tx53_fixup_flexcan(blob);
+       karo_fdt_fixup_flexcan(blob, stk5_v5);
        tx53_fixup_rtc(blob);
-       karo_fdt_update_fb_mode(blob, getenv("video_mode"));
+       video_mode = karo_fdt_set_display(video_mode, "/soc", "/soc/aips/ldb");
+       karo_fdt_update_fb_mode(blob, video_mode);
 }
 #endif /* CONFIG_OF_BOARD_SETUP */