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(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 289{
 290        int which_tsec = -1;
 291        unsigned char mask;
 292        unsigned char switch_mask;
 293
 294        if ((argc > 2) && (strcmp(argv[1], "all") != 0))
 295                which_tsec = simple_strtoul(argv[1], NULL, 0);
 296
 297        switch (which_tsec) {
 298#ifdef CONFIG_TSEC1
 299        case 1:
 300                mask = PIXIS_VSPEED2_TSEC1SER;
 301                switch_mask = PIXIS_VCFGEN1_TSEC1SER;
 302                break;
 303#endif
 304#ifdef CONFIG_TSEC2
 305        case 2:
 306                mask = PIXIS_VSPEED2_TSEC2SER;
 307                switch_mask = PIXIS_VCFGEN1_TSEC2SER;
 308                break;
 309#endif
 310#ifdef CONFIG_TSEC3
 311        case 3:
 312                mask = PIXIS_VSPEED2_TSEC3SER;
 313                switch_mask = PIXIS_VCFGEN1_TSEC3SER;
 314                break;
 315#endif
 316#ifdef CONFIG_TSEC4
 317        case 4:
 318                mask = PIXIS_VSPEED2_TSEC4SER;
 319                switch_mask = PIXIS_VCFGEN1_TSEC4SER;
 320                break;
 321#endif
 322        default:
 323                mask = PIXIS_VSPEED2_MASK;
 324                switch_mask = PIXIS_VCFGEN1_MASK;
 325                break;
 326        }
 327
 328        /* Toggle whether the switches or FPGA control the settings */
 329        if (!strcmp(argv[argc - 1], "switch"))
 330                clrbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
 331        else
 332                setbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
 333
 334        /* If it's not the switches, enable or disable SGMII, as specified */
 335        if (!strcmp(argv[argc - 1], "on"))
 336                clrbits_8(pixis_base + PIXIS_VSPEED2, mask);
 337        else if (!strcmp(argv[argc - 1], "off"))
 338                setbits_8(pixis_base + PIXIS_VSPEED2, mask);
 339
 340        return 0;
 341}
 342
 343U_BOOT_CMD(
 344        pixis_set_sgmii, CONFIG_SYS_MAXARGS, 1, pixis_set_sgmii,
 345        "pixis_set_sgmii"
 346        " - Enable or disable SGMII mode for a given TSEC \n",
 347        "\npixis_set_sgmii [TSEC num] <on|off|switch>\n"
 348        "    TSEC num: 1,2,3,4 or 'all'.  'all' is default.\n"
 349        "    on - enables SGMII\n"
 350        "    off - disables SGMII\n"
 351        "    switch - use switch settings"
 352);
 353
 354#endif
 355
 356/*
 357 * This function takes the non-integral cpu:mpx pll ratio
 358 * and converts it to an integer that can be used to assign
 359 * FPGA register values.
 360 * input: strptr i.e. argv[2]
 361 */
 362static unsigned long strfractoint(char *strptr)
 363{
 364        int i, j;
 365        int mulconst;
 366        int no_dec = 0;
 367        unsigned long intval = 0, decval = 0;
 368        char intarr[3], decarr[3];
 369
 370        /* Assign the integer part to intarr[]
 371         * If there is no decimal point i.e.
 372         * if the ratio is an integral value
 373         * simply create the intarr.
 374         */
 375        i = 0;
 376        while (strptr[i] != '.') {
 377                if (strptr[i] == 0) {
 378                        no_dec = 1;
 379                        break;
 380                }
 381                intarr[i] = strptr[i];
 382                i++;
 383        }
 384
 385        intarr[i] = '\0';
 386
 387        if (no_dec) {
 388                /* Currently needed only for single digit corepll ratios */
 389                mulconst = 10;
 390                decval = 0;
 391        } else {
 392                j = 0;
 393                i++;            /* Skipping the decimal point */
 394                while ((strptr[i] >= '0') && (strptr[i] <= '9')) {
 395                        decarr[j] = strptr[i];
 396                        i++;
 397                        j++;
 398                }
 399
 400                decarr[j] = '\0';
 401
 402                mulconst = 1;
 403                for (i = 0; i < j; i++)
 404                        mulconst *= 10;
 405                decval = simple_strtoul(decarr, NULL, 10);
 406        }
 407
 408        intval = simple_strtoul(intarr, NULL, 10);
 409        intval = intval * mulconst;
 410
 411        return intval + decval;
 412}
 413
 414static int pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 415{
 416        unsigned int i;
 417        char *p_cf = NULL;
 418        char *p_cf_sysclk = NULL;
 419        char *p_cf_corepll = NULL;
 420        char *p_cf_mpxpll = NULL;
 421        char *p_altbank = NULL;
 422        char *p_wd = NULL;
 423        int unknown_param = 0;
 424
 425        /*
 426         * No args is a simple reset request.
 427         */
 428        if (argc <= 1) {
 429                pixis_reset();
 430                /* not reached */
 431        }
 432
 433        for (i = 1; i < argc; i++) {
 434                if (strcmp(argv[i], "cf") == 0) {
 435                        p_cf = argv[i];
 436                        if (i + 3 >= argc) {
 437                                break;
 438                        }
 439                        p_cf_sysclk = argv[i+1];
 440                        p_cf_corepll = argv[i+2];
 441                        p_cf_mpxpll = argv[i+3];
 442                        i += 3;
 443                        continue;
 444                }
 445
 446                if (strcmp(argv[i], "altbank") == 0) {
 447                        p_altbank = argv[i];
 448                        continue;
 449                }
 450
 451                if (strcmp(argv[i], "wd") == 0) {
 452                        p_wd = argv[i];
 453                        continue;
 454                }
 455
 456                unknown_param = 1;
 457        }
 458
 459        /*
 460         * Check that cf has all required parms
 461         */
 462        if ((p_cf && !(p_cf_sysclk && p_cf_corepll && p_cf_mpxpll))
 463            ||  unknown_param) {
 464#ifdef CONFIG_SYS_LONGHELP
 465                puts(cmdtp->help);
 466                putc('\n');
 467#endif
 468                return 1;
 469        }
 470
 471        /*
 472         * PIXIS seems to be sensitive to the ordering of
 473         * the registers that are touched.
 474         */
 475        read_from_px_regs(0);
 476
 477        if (p_altbank)
 478                read_from_px_regs_altbank(0);
 479
 480        clear_altbank();
 481
 482        /*
 483         * Clock configuration specified.
 484         */
 485        if (p_cf) {
 486                unsigned long sysclk;
 487                unsigned long corepll;
 488                unsigned long mpxpll;
 489
 490                sysclk = simple_strtoul(p_cf_sysclk, NULL, 10);
 491                corepll = strfractoint(p_cf_corepll);
 492                mpxpll = simple_strtoul(p_cf_mpxpll, NULL, 10);
 493
 494                if (!(set_px_sysclk(sysclk)
 495                      && set_px_corepll(corepll)
 496                      && set_px_mpxpll(mpxpll))) {
 497#ifdef CONFIG_SYS_LONGHELP
 498                        puts(cmdtp->help);
 499                        putc('\n');
 500#endif
 501                        return 1;
 502                }
 503                read_from_px_regs(1);
 504        }
 505
 506        /*
 507         * Altbank specified
 508         *
 509         * NOTE CHANGE IN BEHAVIOR: previous code would default
 510         * to enabling watchdog if altbank is specified.
 511         * Now the watchdog must be enabled explicitly using 'wd'.
 512         */
 513        if (p_altbank) {
 514                set_altbank();
 515                read_from_px_regs_altbank(1);
 516        }
 517
 518        /*
 519         * Reset with watchdog specified.
 520         */
 521        if (p_wd)
 522                set_px_go_with_watchdog();
 523        else
 524                set_px_go();
 525
 526        /*
 527         * Shouldn't be reached.
 528         */
 529        return 0;
 530}
 531
 532
 533U_BOOT_CMD(
 534        pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
 535        "Reset the board using the FPGA sequencer",
 536        "    pixis_reset\n"
 537        "    pixis_reset [altbank]\n"
 538        "    pixis_reset altbank wd\n"
 539        "    pixis_reset altbank cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
 540        "    pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>"
 541);
 542