uboot/board/freescale/common/pixis.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2006,2010 Freescale Semiconductor
   4 * Jeff Brown
   5 * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include <asm/io.h>
  11
  12#define pixis_base (u8 *)PIXIS_BASE
  13
  14/*
  15 * Simple board reset.
  16 */
  17void pixis_reset(void)
  18{
  19        out_8(pixis_base + PIXIS_RST, 0);
  20
  21        while (1);
  22}
  23
  24/*
  25 * Per table 27, page 58 of MPC8641HPCN spec.
  26 */
  27static int set_px_sysclk(unsigned long sysclk)
  28{
  29        u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux;
  30
  31        switch (sysclk) {
  32        case 33:
  33                sysclk_s = 0x04;
  34                sysclk_r = 0x04;
  35                sysclk_v = 0x07;
  36                sysclk_aux = 0x00;
  37                break;
  38        case 40:
  39                sysclk_s = 0x01;
  40                sysclk_r = 0x1F;
  41                sysclk_v = 0x20;
  42                sysclk_aux = 0x01;
  43                break;
  44        case 50:
  45                sysclk_s = 0x01;
  46                sysclk_r = 0x1F;
  47                sysclk_v = 0x2A;
  48                sysclk_aux = 0x02;
  49                break;
  50        case 66:
  51                sysclk_s = 0x01;
  52                sysclk_r = 0x04;
  53                sysclk_v = 0x04;
  54                sysclk_aux = 0x03;
  55                break;
  56        case 83:
  57                sysclk_s = 0x01;
  58                sysclk_r = 0x1F;
  59                sysclk_v = 0x4B;
  60                sysclk_aux = 0x04;
  61                break;
  62        case 100:
  63                sysclk_s = 0x01;
  64                sysclk_r = 0x1F;
  65                sysclk_v = 0x5C;
  66                sysclk_aux = 0x05;
  67                break;
  68        case 134:
  69                sysclk_s = 0x06;
  70                sysclk_r = 0x1F;
  71                sysclk_v = 0x3B;
  72                sysclk_aux = 0x06;
  73                break;
  74        case 166:
  75                sysclk_s = 0x06;
  76                sysclk_r = 0x1F;
  77                sysclk_v = 0x4B;
  78                sysclk_aux = 0x07;
  79                break;
  80        default:
  81                printf("Unsupported SYSCLK frequency.\n");
  82                return 0;
  83        }
  84
  85        vclkh = (sysclk_s << 5) | sysclk_r;
  86        vclkl = sysclk_v;
  87
  88        out_8(pixis_base + PIXIS_VCLKH, vclkh);
  89        out_8(pixis_base + PIXIS_VCLKL, vclkl);
  90
  91        out_8(pixis_base + PIXIS_AUX, sysclk_aux);
  92
  93        return 1;
  94}
  95
  96/* Set the CFG_SYSPLL bits
  97 *
  98 * This only has effect if PX_VCFGEN0[SYSPLL]=1, which is true if
  99 * read_from_px_regs() is called.
 100 */
 101static int set_px_mpxpll(unsigned long mpxpll)
 102{
 103        switch (mpxpll) {
 104        case 2:
 105        case 4:
 106        case 6:
 107        case 8:
 108        case 10:
 109        case 12:
 110        case 14:
 111        case 16:
 112                clrsetbits_8(pixis_base + PIXIS_VSPEED1, 0x1F, mpxpll);
 113                return 1;
 114        }
 115
 116        printf("Unsupported MPXPLL ratio.\n");
 117        return 0;
 118}
 119
 120static int set_px_corepll(unsigned long corepll)
 121{
 122        u8 val;
 123
 124        switch (corepll) {
 125        case 20:
 126                val = 0x08;
 127                break;
 128        case 25:
 129                val = 0x0C;
 130                break;
 131        case 30:
 132                val = 0x10;
 133                break;
 134        case 35:
 135                val = 0x1C;
 136                break;
 137        case 40:
 138                val = 0x14;
 139                break;
 140        case 45:
 141                val = 0x0E;
 142                break;
 143        default:
 144                printf("Unsupported COREPLL ratio.\n");
 145                return 0;
 146        }
 147
 148        clrsetbits_8(pixis_base + PIXIS_VSPEED0, 0x1F, val);
 149        return 1;
 150}
 151
 152#ifndef CONFIG_SYS_PIXIS_VCFGEN0_ENABLE
 153#define CONFIG_SYS_PIXIS_VCFGEN0_ENABLE         0x1C
 154#endif
 155
 156/* Tell the PIXIS where to find the COREPLL, MPXPLL, SYSCLK values
 157 *
 158 * The PIXIS can be programmed to look at either the on-board dip switches
 159 * or various other PIXIS registers to determine the values for COREPLL,
 160 * MPXPLL, and SYSCLK.
 161 *
 162 * CONFIG_SYS_PIXIS_VCFGEN0_ENABLE is the value to write to the PIXIS_VCFGEN0
 163 * register that tells the pixis to use the various PIXIS register.
 164 */
 165static void read_from_px_regs(int set)
 166{
 167        u8 tmp = in_8(pixis_base + PIXIS_VCFGEN0);
 168
 169        if (set)
 170                tmp = tmp | CONFIG_SYS_PIXIS_VCFGEN0_ENABLE;
 171        else
 172                tmp = tmp & ~CONFIG_SYS_PIXIS_VCFGEN0_ENABLE;
 173
 174        out_8(pixis_base + PIXIS_VCFGEN0, tmp);
 175}
 176
 177/* CONFIG_SYS_PIXIS_VBOOT_ENABLE is the value to write to the PX_VCFGEN1
 178 * register that tells the pixis to use the PX_VBOOT[LBMAP] register.
 179 */
 180#ifndef CONFIG_SYS_PIXIS_VBOOT_ENABLE
 181#define CONFIG_SYS_PIXIS_VBOOT_ENABLE   0x04
 182#endif
 183
 184/* Configure the source of the boot location
 185 *
 186 * The PIXIS can be programmed to look at either the on-board dip switches
 187 * or the PX_VBOOT[LBMAP] register to determine where we should boot.
 188 *
 189 * If we want to boot from the alternate boot bank, we need to tell the PIXIS
 190 * to ignore the on-board dip switches and use the PX_VBOOT[LBMAP] instead.
 191 */
 192static void read_from_px_regs_altbank(int set)
 193{
 194        u8 tmp = in_8(pixis_base + PIXIS_VCFGEN1);
 195
 196        if (set)
 197                tmp = tmp | CONFIG_SYS_PIXIS_VBOOT_ENABLE;
 198        else
 199                tmp = tmp & ~CONFIG_SYS_PIXIS_VBOOT_ENABLE;
 200
 201        out_8(pixis_base + PIXIS_VCFGEN1, tmp);
 202}
 203
 204/* CONFIG_SYS_PIXIS_VBOOT_MASK contains the bits to set in VBOOT register that
 205 * tells the PIXIS what the alternate flash bank is.
 206 *
 207 * Note that it's not really a mask.  It contains the actual LBMAP bits that
 208 * must be set to select the alternate bank.  This code assumes that the
 209 * primary bank has these bits set to 0, and the alternate bank has these
 210 * bits set to 1.
 211 */
 212#ifndef CONFIG_SYS_PIXIS_VBOOT_MASK
 213#define CONFIG_SYS_PIXIS_VBOOT_MASK     (0x40)
 214#endif
 215
 216/* Tell the PIXIS to boot from the default flash bank
 217 *
 218 * Program the default flash bank into the VBOOT register.  This register is
 219 * used only if PX_VCFGEN1[FLASH]=1.
 220 */
 221static void clear_altbank(void)
 222{
 223        clrbits_8(pixis_base + PIXIS_VBOOT, CONFIG_SYS_PIXIS_VBOOT_MASK);
 224}
 225
 226/* Tell the PIXIS to boot from the alternate flash bank
 227 *
 228 * Program the alternate flash bank into the VBOOT register.  This register is
 229 * used only if PX_VCFGEN1[FLASH]=1.
 230 */
 231static void set_altbank(void)
 232{
 233        setbits_8(pixis_base + PIXIS_VBOOT, CONFIG_SYS_PIXIS_VBOOT_MASK);
 234}
 235
 236/* Reset the board with watchdog disabled.
 237 *
 238 * This respects the altbank setting.
 239 */
 240static void set_px_go(void)
 241{
 242        /* Disable the VELA sequencer and watchdog */
 243        clrbits_8(pixis_base + PIXIS_VCTL, 9);
 244
 245        /* Reboot by starting the VELA sequencer */
 246        setbits_8(pixis_base + PIXIS_VCTL, 0x1);
 247
 248        while (1);
 249}
 250
 251/* Reset the board with watchdog enabled.
 252 *
 253 * This respects the altbank setting.
 254 */
 255static void set_px_go_with_watchdog(void)
 256{
 257        /* Disable the VELA sequencer */
 258        clrbits_8(pixis_base + PIXIS_VCTL, 1);
 259
 260        /* Enable the watchdog and reboot by starting the VELA sequencer */
 261        setbits_8(pixis_base + PIXIS_VCTL, 0x9);
 262
 263        while (1);
 264}
 265
 266/* Disable the watchdog
 267 *
 268 */
 269static int pixis_disable_watchdog_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
 270                                      char *const argv[])
 271{
 272        /* Disable the VELA sequencer and the watchdog */
 273        clrbits_8(pixis_base + PIXIS_VCTL, 9);
 274
 275        return 0;
 276}
 277
 278U_BOOT_CMD(
 279        diswd, 1, 0, pixis_disable_watchdog_cmd,
 280        "Disable watchdog timer",
 281        ""
 282);
 283
 284#ifdef CONFIG_PIXIS_SGMII_CMD
 285
 286/* Enable or disable SGMII mode for a TSEC
 287 */
 288static int pixis_set_sgmii(struct cmd_tbl *cmdtp, int flag, int argc,
 289                           char *const argv[])
 290{
 291        int which_tsec = -1;
 292        unsigned char mask;
 293        unsigned char switch_mask;
 294
 295        if ((argc > 2) && (strcmp(argv[1], "all") != 0))
 296                which_tsec = simple_strtoul(argv[1], NULL, 0);
 297
 298        switch (which_tsec) {
 299#ifdef CONFIG_TSEC1
 300        case 1:
 301                mask = PIXIS_VSPEED2_TSEC1SER;
 302                switch_mask = PIXIS_VCFGEN1_TSEC1SER;
 303                break;
 304#endif
 305#ifdef CONFIG_TSEC2
 306        case 2:
 307                mask = PIXIS_VSPEED2_TSEC2SER;
 308                switch_mask = PIXIS_VCFGEN1_TSEC2SER;
 309                break;
 310#endif
 311#ifdef CONFIG_TSEC3
 312        case 3:
 313                mask = PIXIS_VSPEED2_TSEC3SER;
 314                switch_mask = PIXIS_VCFGEN1_TSEC3SER;
 315                break;
 316#endif
 317#ifdef CONFIG_TSEC4
 318        case 4:
 319                mask = PIXIS_VSPEED2_TSEC4SER;
 320                switch_mask = PIXIS_VCFGEN1_TSEC4SER;
 321                break;
 322#endif
 323        default:
 324                mask = PIXIS_VSPEED2_MASK;
 325                switch_mask = PIXIS_VCFGEN1_MASK;
 326                break;
 327        }
 328
 329        /* Toggle whether the switches or FPGA control the settings */
 330        if (!strcmp(argv[argc - 1], "switch"))
 331                clrbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
 332        else
 333                setbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
 334
 335        /* If it's not the switches, enable or disable SGMII, as specified */
 336        if (!strcmp(argv[argc - 1], "on"))
 337                clrbits_8(pixis_base + PIXIS_VSPEED2, mask);
 338        else if (!strcmp(argv[argc - 1], "off"))
 339                setbits_8(pixis_base + PIXIS_VSPEED2, mask);
 340
 341        return 0;
 342}
 343
 344U_BOOT_CMD(
 345        pixis_set_sgmii, CONFIG_SYS_MAXARGS, 1, pixis_set_sgmii,
 346        "pixis_set_sgmii"
 347        " - Enable or disable SGMII mode for a given TSEC \n",
 348        "\npixis_set_sgmii [TSEC num] <on|off|switch>\n"
 349        "    TSEC num: 1,2,3,4 or 'all'.  'all' is default.\n"
 350        "    on - enables SGMII\n"
 351        "    off - disables SGMII\n"
 352        "    switch - use switch settings"
 353);
 354
 355#endif
 356
 357/*
 358 * This function takes the non-integral cpu:mpx pll ratio
 359 * and converts it to an integer that can be used to assign
 360 * FPGA register values.
 361 * input: strptr i.e. argv[2]
 362 */
 363static unsigned long strfractoint(char *strptr)
 364{
 365        int i, j;
 366        int mulconst;
 367        int no_dec = 0;
 368        unsigned long intval = 0, decval = 0;
 369        char intarr[3], decarr[3];
 370
 371        /* Assign the integer part to intarr[]
 372         * If there is no decimal point i.e.
 373         * if the ratio is an integral value
 374         * simply create the intarr.
 375         */
 376        i = 0;
 377        while (strptr[i] != '.') {
 378                if (strptr[i] == 0) {
 379                        no_dec = 1;
 380                        break;
 381                }
 382                intarr[i] = strptr[i];
 383                i++;
 384        }
 385
 386        intarr[i] = '\0';
 387
 388        if (no_dec) {
 389                /* Currently needed only for single digit corepll ratios */
 390                mulconst = 10;
 391                decval = 0;
 392        } else {
 393                j = 0;
 394                i++;            /* Skipping the decimal point */
 395                while ((strptr[i] >= '0') && (strptr[i] <= '9')) {
 396                        decarr[j] = strptr[i];
 397                        i++;
 398                        j++;
 399                }
 400
 401                decarr[j] = '\0';
 402
 403                mulconst = 1;
 404                for (i = 0; i < j; i++)
 405                        mulconst *= 10;
 406                decval = dectoul(decarr, NULL);
 407        }
 408
 409        intval = dectoul(intarr, NULL);
 410        intval = intval * mulconst;
 411
 412        return intval + decval;
 413}
 414
 415static int pixis_reset_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
 416                           char *const argv[])
 417{
 418        unsigned int i;
 419        char *p_cf = NULL;
 420        char *p_cf_sysclk = NULL;
 421        char *p_cf_corepll = NULL;
 422        char *p_cf_mpxpll = NULL;
 423        char *p_altbank = NULL;
 424        char *p_wd = NULL;
 425        int unknown_param = 0;
 426
 427        /*
 428         * No args is a simple reset request.
 429         */
 430        if (argc <= 1) {
 431                pixis_reset();
 432                /* not reached */
 433        }
 434
 435        for (i = 1; i < argc; i++) {
 436                if (strcmp(argv[i], "cf") == 0) {
 437                        p_cf = argv[i];
 438                        if (i + 3 >= argc) {
 439                                break;
 440                        }
 441                        p_cf_sysclk = argv[i+1];
 442                        p_cf_corepll = argv[i+2];
 443                        p_cf_mpxpll = argv[i+3];
 444                        i += 3;
 445                        continue;
 446                }
 447
 448                if (strcmp(argv[i], "altbank") == 0) {
 449                        p_altbank = argv[i];
 450                        continue;
 451                }
 452
 453                if (strcmp(argv[i], "wd") == 0) {
 454                        p_wd = argv[i];
 455                        continue;
 456                }
 457
 458                unknown_param = 1;
 459        }
 460
 461        /*
 462         * Check that cf has all required parms
 463         */
 464        if ((p_cf && !(p_cf_sysclk && p_cf_corepll && p_cf_mpxpll))
 465            ||  unknown_param) {
 466#ifdef CONFIG_SYS_LONGHELP
 467                puts(cmdtp->help);
 468                putc('\n');
 469#endif
 470                return 1;
 471        }
 472
 473        /*
 474         * PIXIS seems to be sensitive to the ordering of
 475         * the registers that are touched.
 476         */
 477        read_from_px_regs(0);
 478
 479        if (p_altbank)
 480                read_from_px_regs_altbank(0);
 481
 482        clear_altbank();
 483
 484        /*
 485         * Clock configuration specified.
 486         */
 487        if (p_cf) {
 488                unsigned long sysclk;
 489                unsigned long corepll;
 490                unsigned long mpxpll;
 491
 492                sysclk = dectoul(p_cf_sysclk, NULL);
 493                corepll = strfractoint(p_cf_corepll);
 494                mpxpll = dectoul(p_cf_mpxpll, NULL);
 495
 496                if (!(set_px_sysclk(sysclk)
 497                      && set_px_corepll(corepll)
 498                      && set_px_mpxpll(mpxpll))) {
 499#ifdef CONFIG_SYS_LONGHELP
 500                        puts(cmdtp->help);
 501                        putc('\n');
 502#endif
 503                        return 1;
 504                }
 505                read_from_px_regs(1);
 506        }
 507
 508        /*
 509         * Altbank specified
 510         *
 511         * NOTE CHANGE IN BEHAVIOR: previous code would default
 512         * to enabling watchdog if altbank is specified.
 513         * Now the watchdog must be enabled explicitly using 'wd'.
 514         */
 515        if (p_altbank) {
 516                set_altbank();
 517                read_from_px_regs_altbank(1);
 518        }
 519
 520        /*
 521         * Reset with watchdog specified.
 522         */
 523        if (p_wd)
 524                set_px_go_with_watchdog();
 525        else
 526                set_px_go();
 527
 528        /*
 529         * Shouldn't be reached.
 530         */
 531        return 0;
 532}
 533
 534
 535U_BOOT_CMD(
 536        pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
 537        "Reset the board using the FPGA sequencer",
 538        "    pixis_reset\n"
 539        "    pixis_reset [altbank]\n"
 540        "    pixis_reset altbank wd\n"
 541        "    pixis_reset altbank cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
 542        "    pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>"
 543);
 544