Merge branch 'master' of git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / board / freescale / common / pixis.c
index 45dcf4d..7210512 100644 (file)
@@ -25,9 +25,9 @@
 #include <common.h>
 #include <command.h>
 #include <watchdog.h>
-
-#ifdef CONFIG_FSL_PIXIS
 #include <asm/cache.h>
+#include <asm/io.h>
+
 #include "pixis.h"
 
 
@@ -39,7 +39,8 @@ static ulong strfractoint(uchar *strptr);
  */
 void pixis_reset(void)
 {
-    out8(PIXIS_BASE + PIXIS_RST, 0);
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
+       out_8(pixis_base + PIXIS_RST, 0);
 }
 
 
@@ -49,6 +50,7 @@ void pixis_reset(void)
 int set_px_sysclk(ulong sysclk)
 {
        u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
        switch (sysclk) {
        case 33:
@@ -107,10 +109,10 @@ int set_px_sysclk(ulong sysclk)
        vclkh = (sysclk_s << 5) | sysclk_r;
        vclkl = sysclk_v;
 
-       out8(PIXIS_BASE + PIXIS_VCLKH, vclkh);
-       out8(PIXIS_BASE + PIXIS_VCLKL, vclkl);
+       out_8(pixis_base + PIXIS_VCLKH, vclkh);
+       out_8(pixis_base + PIXIS_VCLKL, vclkl);
 
-       out8(PIXIS_BASE + PIXIS_AUX, sysclk_aux);
+       out_8(pixis_base + PIXIS_AUX, sysclk_aux);
 
        return 1;
 }
@@ -120,6 +122,7 @@ int set_px_mpxpll(ulong mpxpll)
 {
        u8 tmp;
        u8 val;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
        switch (mpxpll) {
        case 2:
@@ -137,9 +140,9 @@ int set_px_mpxpll(ulong mpxpll)
                return 0;
        }
 
-       tmp = in8(PIXIS_BASE + PIXIS_VSPEED1);
+       tmp = in_8(pixis_base + PIXIS_VSPEED1);
        tmp = (tmp & 0xF0) | (val & 0x0F);
-       out8(PIXIS_BASE + PIXIS_VSPEED1, tmp);
+       out_8(pixis_base + PIXIS_VSPEED1, tmp);
 
        return 1;
 }
@@ -149,6 +152,7 @@ int set_px_corepll(ulong corepll)
 {
        u8 tmp;
        u8 val;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
        switch ((int)corepll) {
        case 20:
@@ -174,9 +178,9 @@ int set_px_corepll(ulong corepll)
                return 0;
        }
 
-       tmp = in8(PIXIS_BASE + PIXIS_VSPEED0);
+       tmp = in_8(pixis_base + PIXIS_VSPEED0);
        tmp = (tmp & 0xE0) | (val & 0x1F);
-       out8(PIXIS_BASE + PIXIS_VSPEED0, tmp);
+       out_8(pixis_base + PIXIS_VSPEED0, tmp);
 
        return 1;
 }
@@ -184,69 +188,86 @@ int set_px_corepll(ulong corepll)
 
 void read_from_px_regs(int set)
 {
-       u8 mask = 0x1C;
-       u8 tmp = in8(PIXIS_BASE + PIXIS_VCFGEN0);
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
+       u8 mask = 0x1C; /* COREPLL, MPXPLL, SYSCLK controlled by PIXIS */
+       u8 tmp = in_8(pixis_base + PIXIS_VCFGEN0);
 
        if (set)
                tmp = tmp | mask;
        else
                tmp = tmp & ~mask;
-       out8(PIXIS_BASE + PIXIS_VCFGEN0, tmp);
+       out_8(pixis_base + PIXIS_VCFGEN0, tmp);
 }
 
 
 void read_from_px_regs_altbank(int set)
 {
-       u8 mask = 0x04;
-       u8 tmp = in8(PIXIS_BASE + PIXIS_VCFGEN1);
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
+       u8 mask = 0x04; /* FLASHBANK and FLASHMAP controlled by PIXIS */
+       u8 tmp = in_8(pixis_base + PIXIS_VCFGEN1);
 
        if (set)
                tmp = tmp | mask;
        else
                tmp = tmp & ~mask;
-       out8(PIXIS_BASE + PIXIS_VCFGEN1, tmp);
+       out_8(pixis_base + PIXIS_VCFGEN1, tmp);
 }
 
-#ifndef CFG_PIXIS_VBOOT_MASK
-#define CFG_PIXIS_VBOOT_MASK   0x40
+#ifndef CONFIG_SYS_PIXIS_VBOOT_MASK
+#define CONFIG_SYS_PIXIS_VBOOT_MASK    (0x40)
 #endif
 
+void clear_altbank(void)
+{
+       u8 tmp;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
+
+       tmp = in_8(pixis_base + PIXIS_VBOOT);
+       tmp &= ~CONFIG_SYS_PIXIS_VBOOT_MASK;
+
+       out_8(pixis_base + PIXIS_VBOOT, tmp);
+}
+
+
 void set_altbank(void)
 {
        u8 tmp;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
-       tmp = in8(PIXIS_BASE + PIXIS_VBOOT);
-       tmp ^= CFG_PIXIS_VBOOT_MASK;
+       tmp = in_8(pixis_base + PIXIS_VBOOT);
+       tmp |= CONFIG_SYS_PIXIS_VBOOT_MASK;
 
-       out8(PIXIS_BASE + PIXIS_VBOOT, tmp);
+       out_8(pixis_base + PIXIS_VBOOT, tmp);
 }
 
 
 void set_px_go(void)
 {
        u8 tmp;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
-       tmp = in8(PIXIS_BASE + PIXIS_VCTL);
-       tmp = tmp & 0x1E;
-       out8(PIXIS_BASE + PIXIS_VCTL, tmp);
+       tmp = in_8(pixis_base + PIXIS_VCTL);
+       tmp = tmp & 0x1E;                       /* clear GO bit */
+       out_8(pixis_base + PIXIS_VCTL, tmp);
 
-       tmp = in8(PIXIS_BASE + PIXIS_VCTL);
-       tmp = tmp | 0x01;
-       out8(PIXIS_BASE + PIXIS_VCTL, tmp);
+       tmp = in_8(pixis_base + PIXIS_VCTL);
+       tmp = tmp | 0x01;       /* set GO bit - start reset sequencer */
+       out_8(pixis_base + PIXIS_VCTL, tmp);
 }
 
 
 void set_px_go_with_watchdog(void)
 {
        u8 tmp;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
-       tmp = in8(PIXIS_BASE + PIXIS_VCTL);
+       tmp = in_8(pixis_base + PIXIS_VCTL);
        tmp = tmp & 0x1E;
-       out8(PIXIS_BASE + PIXIS_VCTL, tmp);
+       out_8(pixis_base + PIXIS_VCTL, tmp);
 
-       tmp = in8(PIXIS_BASE + PIXIS_VCTL);
+       tmp = in_8(pixis_base + PIXIS_VCTL);
        tmp = tmp | 0x09;
-       out8(PIXIS_BASE + PIXIS_VCTL, tmp);
+       out_8(pixis_base + PIXIS_VCTL, tmp);
 }
 
 
@@ -254,23 +275,95 @@ int pixis_disable_watchdog_cmd(cmd_tbl_t *cmdtp,
                               int flag, int argc, char *argv[])
 {
        u8 tmp;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
 
-       tmp = in8(PIXIS_BASE + PIXIS_VCTL);
+       tmp = in_8(pixis_base + PIXIS_VCTL);
        tmp = tmp & 0x1E;
-       out8(PIXIS_BASE + PIXIS_VCTL, tmp);
+       out_8(pixis_base + PIXIS_VCTL, tmp);
 
        /* setting VCTL[WDEN] to 0 to disable watch dog */
-       tmp = in8(PIXIS_BASE + PIXIS_VCTL);
+       tmp = in_8(pixis_base + PIXIS_VCTL);
        tmp &= ~0x08;
-       out8(PIXIS_BASE + PIXIS_VCTL, tmp);
+       out_8(pixis_base + PIXIS_VCTL, tmp);
 
        return 0;
 }
 
 U_BOOT_CMD(
-          diswd, 1, 0, pixis_disable_watchdog_cmd,
-          "diswd       - Disable watchdog timer \n",
-          NULL);
+       diswd, 1, 0, pixis_disable_watchdog_cmd,
+       "Disable watchdog timer",
+       ""
+);
+
+#ifdef CONFIG_PIXIS_SGMII_CMD
+int pixis_set_sgmii(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int which_tsec = -1;
+       u8 *pixis_base = (u8 *)PIXIS_BASE;
+       uchar mask;
+       uchar switch_mask;
+
+       if (argc > 2)
+               if (strcmp(argv[1], "all") != 0)
+                       which_tsec = simple_strtoul(argv[1], NULL, 0);
+
+       switch (which_tsec) {
+#ifdef CONFIG_TSEC1
+       case 1:
+               mask = PIXIS_VSPEED2_TSEC1SER;
+               switch_mask = PIXIS_VCFGEN1_TSEC1SER;
+               break;
+#endif
+#ifdef CONFIG_TSEC2
+       case 2:
+               mask = PIXIS_VSPEED2_TSEC2SER;
+               switch_mask = PIXIS_VCFGEN1_TSEC2SER;
+               break;
+#endif
+#ifdef CONFIG_TSEC3
+       case 3:
+               mask = PIXIS_VSPEED2_TSEC3SER;
+               switch_mask = PIXIS_VCFGEN1_TSEC3SER;
+               break;
+#endif
+#ifdef CONFIG_TSEC4
+       case 4:
+               mask = PIXIS_VSPEED2_TSEC4SER;
+               switch_mask = PIXIS_VCFGEN1_TSEC4SER;
+               break;
+#endif
+       default:
+               mask = PIXIS_VSPEED2_MASK;
+               switch_mask = PIXIS_VCFGEN1_MASK;
+               break;
+       }
+
+       /* Toggle whether the switches or FPGA control the settings */
+       if (!strcmp(argv[argc - 1], "switch"))
+               clrbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
+       else
+               setbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
+
+       /* If it's not the switches, enable or disable SGMII, as specified */
+       if (!strcmp(argv[argc - 1], "on"))
+               clrbits_8(pixis_base + PIXIS_VSPEED2, mask);
+       else if (!strcmp(argv[argc - 1], "off"))
+               setbits_8(pixis_base + PIXIS_VSPEED2, mask);
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       pixis_set_sgmii, CONFIG_SYS_MAXARGS, 1, pixis_set_sgmii,
+       "pixis_set_sgmii"
+       " - Enable or disable SGMII mode for a given TSEC \n",
+       "\npixis_set_sgmii [TSEC num] <on|off|switch>\n"
+       "    TSEC num: 1,2,3,4 or 'all'.  'all' is default.\n"
+       "    on - enables SGMII\n"
+       "    off - disables SGMII\n"
+       "    switch - use switch settings"
+);
+#endif
 
 /*
  * This function takes the non-integral cpu:mpx pll ratio
@@ -293,7 +386,7 @@ static ulong strfractoint(uchar *strptr)
         * simply create the intarr.
         */
        i = 0;
-       while (strptr[i] != 46) {
+       while (strptr[i] != '.') {
                if (strptr[i] == 0) {
                        no_dec = 1;
                        break;
@@ -313,7 +406,7 @@ static ulong strfractoint(uchar *strptr)
        } else {
                j = 0;
                i++;            /* Skipping the decimal point */
-               while ((strptr[i] > 47) && (strptr[i] < 58)) {
+               while ((strptr[i] >= '0') && (strptr[i] <= '9')) {
                        decarr[j] = strptr[i];
                        i++;
                        j++;
@@ -340,8 +433,14 @@ static ulong strfractoint(uchar *strptr)
 int
 pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-       ulong val;
-       ulong corepll;
+       unsigned int i;
+       char *p_cf = NULL;
+       char *p_cf_sysclk = NULL;
+       char *p_cf_corepll = NULL;
+       char *p_cf_mpxpll = NULL;
+       char *p_altbank = NULL;
+       char *p_wd = NULL;
+       unsigned int unknown_param = 0;
 
        /*
         * No args is a simple reset request.
@@ -351,127 +450,111 @@ pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                /* not reached */
        }
 
-       if (strcmp(argv[1], "cf") == 0) {
+       for (i = 1; i < argc; i++) {
+               if (strcmp(argv[i], "cf") == 0) {
+                       p_cf = argv[i];
+                       if (i + 3 >= argc) {
+                               break;
+                       }
+                       p_cf_sysclk = argv[i+1];
+                       p_cf_corepll = argv[i+2];
+                       p_cf_mpxpll = argv[i+3];
+                       i += 3;
+                       continue;
+               }
 
-               /*
-                * Reset with frequency changed:
-                *    cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>
-                */
-               if (argc < 5) {
-                       puts(cmdtp->usage);
-                       return 1;
+               if (strcmp(argv[i], "altbank") == 0) {
+                       p_altbank = argv[i];
+                       continue;
                }
 
-               read_from_px_regs(0);
-
-               val = set_px_sysclk(simple_strtoul(argv[2], NULL, 10));
-
-               corepll = strfractoint((uchar *)argv[3]);
-               val = val + set_px_corepll(corepll);
-               val = val + set_px_mpxpll(simple_strtoul(argv[4], NULL, 10));
-               if (val == 3) {
-                       puts("Setting registers VCFGEN0 and VCTL\n");
-                       read_from_px_regs(1);
-                       puts("Resetting board with values from ");
-                       puts("VSPEED0, VSPEED1, VCLKH, and VCLKL \n");
-                       set_px_go();
-               } else {
-                       puts(cmdtp->usage);
-                       return 1;
+               if (strcmp(argv[i], "wd") == 0) {
+                       p_wd = argv[i];
+                       continue;
                }
 
-               while (1) ;     /* Not reached */
-
-       } else if (strcmp(argv[1], "altbank") == 0) {
-
-               /*
-                * Reset using alternate flash bank:
-                */
-               if (argv[2] == 0) {
-                       /*
-                        * Reset from alternate bank without changing
-                        * frequency and without watchdog timer enabled.
-                        *      altbank
-                        */
-                       read_from_px_regs(0);
-                       read_from_px_regs_altbank(0);
-                       if (argc > 2) {
-                               puts(cmdtp->usage);
-                               return 1;
-                       }
-                       puts("Setting registers VCFGNE1, VBOOT, and VCTL\n");
-                       set_altbank();
-                       read_from_px_regs_altbank(1);
-                       puts("Resetting board to boot from the other bank.\n");
-                       set_px_go();
-
-               } else if (strcmp(argv[2], "cf") == 0) {
-                       /*
-                        * Reset with frequency changed
-                        *    altbank cf <SYSCLK freq> <COREPLL ratio>
-                        *                              <MPXPLL ratio>
-                        */
-                       read_from_px_regs(0);
-                       read_from_px_regs_altbank(0);
-                       val = set_px_sysclk(simple_strtoul(argv[3], NULL, 10));
-                       corepll = strfractoint((uchar *)argv[4]);
-                       val = val + set_px_corepll(corepll);
-                       val = val + set_px_mpxpll(simple_strtoul(argv[5],
-                                                                NULL, 10));
-                       if (val == 3) {
-                               puts("Setting registers VCFGEN0, VCFGEN1, VBOOT, and VCTL\n");
-                               set_altbank();
-                               read_from_px_regs(1);
-                               read_from_px_regs_altbank(1);
-                               puts("Enabling watchdog timer on the FPGA\n");
-                               puts("Resetting board with values from ");
-                               puts("VSPEED0, VSPEED1, VCLKH and VCLKL ");
-                               puts("to boot from the other bank.\n");
-                               set_px_go_with_watchdog();
-                       } else {
-                               puts(cmdtp->usage);
-                               return 1;
-                       }
+               unknown_param = 1;
+       }
+
+       /*
+        * Check that cf has all required parms
+        */
+       if ((p_cf && !(p_cf_sysclk && p_cf_corepll && p_cf_mpxpll))
+           ||  unknown_param) {
+#ifdef CONFIG_SYS_LONGHELP
+               puts(cmdtp->help);
+#endif
+               return 1;
+       }
+
+       /*
+        * PIXIS seems to be sensitive to the ordering of
+        * the registers that are touched.
+        */
+       read_from_px_regs(0);
+
+       if (p_altbank) {
+               read_from_px_regs_altbank(0);
+       }
+       clear_altbank();
 
-                       while (1) ;     /* Not reached */
-
-               } else if (strcmp(argv[2], "wd") == 0) {
-                       /*
-                        * Reset from alternate bank without changing
-                        * frequencies but with watchdog timer enabled:
-                        *    altbank wd
-                        */
-                       read_from_px_regs(0);
-                       read_from_px_regs_altbank(0);
-                       puts("Setting registers VCFGEN1, VBOOT, and VCTL\n");
-                       set_altbank();
-                       read_from_px_regs_altbank(1);
-                       puts("Enabling watchdog timer on the FPGA\n");
-                       puts("Resetting board to boot from the other bank.\n");
-                       set_px_go_with_watchdog();
-                       while (1) ;     /* Not reached */
-
-               } else {
-                       puts(cmdtp->usage);
+       /*
+        * Clock configuration specified.
+        */
+       if (p_cf) {
+               unsigned long sysclk;
+               unsigned long corepll;
+               unsigned long mpxpll;
+
+               sysclk = simple_strtoul(p_cf_sysclk, NULL, 10);
+               corepll = strfractoint((uchar *) p_cf_corepll);
+               mpxpll = simple_strtoul(p_cf_mpxpll, NULL, 10);
+
+               if (!(set_px_sysclk(sysclk)
+                     && set_px_corepll(corepll)
+                     && set_px_mpxpll(mpxpll))) {
+#ifdef CONFIG_SYS_LONGHELP
+                       puts(cmdtp->help);
+#endif
                        return 1;
                }
+               read_from_px_regs(1);
+       }
+
+       /*
+        * Altbank specified
+        *
+        * NOTE CHANGE IN BEHAVIOR: previous code would default
+        * to enabling watchdog if altbank is specified.
+        * Now the watchdog must be enabled explicitly using 'wd'.
+        */
+       if (p_altbank) {
+               set_altbank();
+               read_from_px_regs_altbank(1);
+       }
 
+       /*
+        * Reset with watchdog specified.
+        */
+       if (p_wd) {
+               set_px_go_with_watchdog();
        } else {
-               puts(cmdtp->usage);
-               return 1;
+               set_px_go();
        }
 
+       /*
+        * Shouldn't be reached.
+        */
        return 0;
 }
 
 
 U_BOOT_CMD(
-       pixis_reset, CFG_MAXARGS, 1, pixis_reset_cmd,
-       "pixis_reset - Reset the board using the FPGA sequencer\n",
+       pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
+       "Reset the board using the FPGA sequencer",
        "    pixis_reset\n"
        "    pixis_reset [altbank]\n"
        "    pixis_reset altbank wd\n"
        "    pixis_reset altbank cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
-       "    pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
-       );
-#endif /* CONFIG_FSL_PIXIS */
+       "    pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>"
+);