uboot/arch/powerpc/cpu/mpc83xx/cpu_init.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <mpc83xx.h>
   9#include <ioports.h>
  10#include <asm/io.h>
  11#ifdef CONFIG_USB_EHCI_FSL
  12#include <usb/ehci-fsl.h>
  13#endif
  14
  15DECLARE_GLOBAL_DATA_PTR;
  16
  17#ifdef CONFIG_QE
  18extern qe_iop_conf_t qe_iop_conf_tab[];
  19extern void qe_config_iopin(u8 port, u8 pin, int dir,
  20                         int open_drain, int assign);
  21extern void qe_init(uint qe_base);
  22extern void qe_reset(void);
  23
  24static void config_qe_ioports(void)
  25{
  26        u8      port, pin;
  27        int     dir, open_drain, assign;
  28        int     i;
  29
  30        for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
  31                port            = qe_iop_conf_tab[i].port;
  32                pin             = qe_iop_conf_tab[i].pin;
  33                dir             = qe_iop_conf_tab[i].dir;
  34                open_drain      = qe_iop_conf_tab[i].open_drain;
  35                assign          = qe_iop_conf_tab[i].assign;
  36                qe_config_iopin(port, pin, dir, open_drain, assign);
  37        }
  38}
  39#endif
  40
  41/*
  42 * Breathe some life into the CPU...
  43 *
  44 * Set up the memory map,
  45 * initialize a bunch of registers,
  46 * initialize the UPM's
  47 */
  48void cpu_init_f (volatile immap_t * im)
  49{
  50        __be32 acr_mask =
  51#ifdef CONFIG_SYS_ACR_PIPE_DEP /* Arbiter pipeline depth */
  52                ACR_PIPE_DEP |
  53#endif
  54#ifdef CONFIG_SYS_ACR_RPTCNT /* Arbiter repeat count */
  55                ACR_RPTCNT |
  56#endif
  57#ifdef CONFIG_SYS_ACR_APARK     /* Arbiter address parking mode */
  58                ACR_APARK |
  59#endif
  60#ifdef CONFIG_SYS_ACR_PARKM     /* Arbiter parking master */
  61                ACR_PARKM |
  62#endif
  63                0;
  64        __be32 acr_val =
  65#ifdef CONFIG_SYS_ACR_PIPE_DEP /* Arbiter pipeline depth */
  66                (CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT) |
  67#endif
  68#ifdef CONFIG_SYS_ACR_RPTCNT /* Arbiter repeat count */
  69                (CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT) |
  70#endif
  71#ifdef CONFIG_SYS_ACR_APARK     /* Arbiter address parking mode */
  72                (CONFIG_SYS_ACR_APARK << ACR_APARK_SHIFT) |
  73#endif
  74#ifdef CONFIG_SYS_ACR_PARKM     /* Arbiter parking master */
  75                (CONFIG_SYS_ACR_PARKM << ACR_PARKM_SHIFT) |
  76#endif
  77                0;
  78        __be32 spcr_mask =
  79#ifdef CONFIG_SYS_SPCR_OPT /* Optimize transactions between CSB and other dev */
  80                SPCR_OPT |
  81#endif
  82#ifdef CONFIG_SYS_SPCR_TSECEP /* all eTSEC's Emergency priority */
  83                SPCR_TSECEP |
  84#endif
  85#ifdef CONFIG_SYS_SPCR_TSEC1EP /* TSEC1 Emergency priority */
  86                SPCR_TSEC1EP |
  87#endif
  88#ifdef CONFIG_SYS_SPCR_TSEC2EP /* TSEC2 Emergency priority */
  89                SPCR_TSEC2EP |
  90#endif
  91                0;
  92        __be32 spcr_val =
  93#ifdef CONFIG_SYS_SPCR_OPT
  94                (CONFIG_SYS_SPCR_OPT << SPCR_OPT_SHIFT) |
  95#endif
  96#ifdef CONFIG_SYS_SPCR_TSECEP /* all eTSEC's Emergency priority */
  97                (CONFIG_SYS_SPCR_TSECEP << SPCR_TSECEP_SHIFT) |
  98#endif
  99#ifdef CONFIG_SYS_SPCR_TSEC1EP /* TSEC1 Emergency priority */
 100                (CONFIG_SYS_SPCR_TSEC1EP << SPCR_TSEC1EP_SHIFT) |
 101#endif
 102#ifdef CONFIG_SYS_SPCR_TSEC2EP /* TSEC2 Emergency priority */
 103                (CONFIG_SYS_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT) |
 104#endif
 105                0;
 106        __be32 sccr_mask =
 107#ifdef CONFIG_SYS_SCCR_ENCCM /* Encryption clock mode */
 108                SCCR_ENCCM |
 109#endif
 110#ifdef CONFIG_SYS_SCCR_PCICM /* PCI & DMA clock mode */
 111                SCCR_PCICM |
 112#endif
 113#ifdef CONFIG_SYS_SCCR_PCIEXP1CM        /* PCIE1 clock mode */
 114                SCCR_PCIEXP1CM |
 115#endif
 116#ifdef CONFIG_SYS_SCCR_PCIEXP2CM        /* PCIE2 clock mode */
 117                SCCR_PCIEXP2CM |
 118#endif
 119#ifdef CONFIG_SYS_SCCR_TSECCM /* all TSEC's clock mode */
 120                SCCR_TSECCM |
 121#endif
 122#ifdef CONFIG_SYS_SCCR_TSEC1CM /* TSEC1 clock mode */
 123                SCCR_TSEC1CM |
 124#endif
 125#ifdef CONFIG_SYS_SCCR_TSEC2CM /* TSEC2 clock mode */
 126                SCCR_TSEC2CM |
 127#endif
 128#ifdef CONFIG_SYS_SCCR_TSEC1ON /* TSEC1 clock switch */
 129                SCCR_TSEC1ON |
 130#endif
 131#ifdef CONFIG_SYS_SCCR_TSEC2ON /* TSEC2 clock switch */
 132                SCCR_TSEC2ON |
 133#endif
 134#ifdef CONFIG_SYS_SCCR_USBMPHCM /* USB MPH clock mode */
 135                SCCR_USBMPHCM |
 136#endif
 137#ifdef CONFIG_SYS_SCCR_USBDRCM /* USB DR clock mode */
 138                SCCR_USBDRCM |
 139#endif
 140#ifdef CONFIG_SYS_SCCR_SATACM /* SATA controller clock mode */
 141                SCCR_SATACM |
 142#endif
 143                0;
 144        __be32 sccr_val =
 145#ifdef CONFIG_SYS_SCCR_ENCCM /* Encryption clock mode */
 146                (CONFIG_SYS_SCCR_ENCCM << SCCR_ENCCM_SHIFT) |
 147#endif
 148#ifdef CONFIG_SYS_SCCR_PCICM /* PCI & DMA clock mode */
 149                (CONFIG_SYS_SCCR_PCICM << SCCR_PCICM_SHIFT) |
 150#endif
 151#ifdef CONFIG_SYS_SCCR_PCIEXP1CM        /* PCIE1 clock mode */
 152                (CONFIG_SYS_SCCR_PCIEXP1CM << SCCR_PCIEXP1CM_SHIFT) |
 153#endif
 154#ifdef CONFIG_SYS_SCCR_PCIEXP2CM        /* PCIE2 clock mode */
 155                (CONFIG_SYS_SCCR_PCIEXP2CM << SCCR_PCIEXP2CM_SHIFT) |
 156#endif
 157#ifdef CONFIG_SYS_SCCR_TSECCM /* all TSEC's clock mode */
 158                (CONFIG_SYS_SCCR_TSECCM << SCCR_TSECCM_SHIFT) |
 159#endif
 160#ifdef CONFIG_SYS_SCCR_TSEC1CM /* TSEC1 clock mode */
 161                (CONFIG_SYS_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT) |
 162#endif
 163#ifdef CONFIG_SYS_SCCR_TSEC2CM /* TSEC2 clock mode */
 164                (CONFIG_SYS_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT) |
 165#endif
 166#ifdef CONFIG_SYS_SCCR_TSEC1ON /* TSEC1 clock switch */
 167                (CONFIG_SYS_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT) |
 168#endif
 169#ifdef CONFIG_SYS_SCCR_TSEC2ON /* TSEC2 clock switch */
 170                (CONFIG_SYS_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT) |
 171#endif
 172#ifdef CONFIG_SYS_SCCR_USBMPHCM /* USB MPH clock mode */
 173                (CONFIG_SYS_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT) |
 174#endif
 175#ifdef CONFIG_SYS_SCCR_USBDRCM /* USB DR clock mode */
 176                (CONFIG_SYS_SCCR_USBDRCM << SCCR_USBDRCM_SHIFT) |
 177#endif
 178#ifdef CONFIG_SYS_SCCR_SATACM /* SATA controller clock mode */
 179                (CONFIG_SYS_SCCR_SATACM << SCCR_SATACM_SHIFT) |
 180#endif
 181                0;
 182        __be32 lcrr_mask =
 183#ifdef CONFIG_SYS_LCRR_DBYP /* PLL bypass */
 184                LCRR_DBYP |
 185#endif
 186#ifdef CONFIG_SYS_LCRR_EADC /* external address delay */
 187                LCRR_EADC |
 188#endif
 189#ifdef CONFIG_SYS_LCRR_CLKDIV /* system clock divider */
 190                LCRR_CLKDIV |
 191#endif
 192                0;
 193        __be32 lcrr_val =
 194#ifdef CONFIG_SYS_LCRR_DBYP /* PLL bypass */
 195                CONFIG_SYS_LCRR_DBYP |
 196#endif
 197#ifdef CONFIG_SYS_LCRR_EADC
 198                CONFIG_SYS_LCRR_EADC |
 199#endif
 200#ifdef CONFIG_SYS_LCRR_CLKDIV /* system clock divider */
 201                CONFIG_SYS_LCRR_CLKDIV |
 202#endif
 203                0;
 204
 205        /* Pointer is writable since we allocated a register for it */
 206        gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
 207
 208        /* Clear initial global data */
 209        memset ((void *) gd, 0, sizeof (gd_t));
 210
 211        /* system performance tweaking */
 212        clrsetbits_be32(&im->arbiter.acr, acr_mask, acr_val);
 213
 214        clrsetbits_be32(&im->sysconf.spcr, spcr_mask, spcr_val);
 215
 216        clrsetbits_be32(&im->clk.sccr, sccr_mask, sccr_val);
 217
 218        /* RSR - Reset Status Register - clear all status (4.6.1.3) */
 219        gd->arch.reset_status = __raw_readl(&im->reset.rsr);
 220        __raw_writel(~(RSR_RES), &im->reset.rsr);
 221
 222        /* AER - Arbiter Event Register - store status */
 223        gd->arch.arbiter_event_attributes = __raw_readl(&im->arbiter.aeatr);
 224        gd->arch.arbiter_event_address = __raw_readl(&im->arbiter.aeadr);
 225
 226        /*
 227         * RMR - Reset Mode Register
 228         * contains checkstop reset enable (4.6.1.4)
 229         */
 230        __raw_writel(RMR_CSRE & (1<<RMR_CSRE_SHIFT), &im->reset.rmr);
 231
 232        /* LCRR - Clock Ratio Register (10.3.1.16)
 233         * write, read, and isync per MPC8379ERM rev.1 CLKDEV field description
 234         */
 235        clrsetbits_be32(&im->im_lbc.lcrr, lcrr_mask, lcrr_val);
 236        __raw_readl(&im->im_lbc.lcrr);
 237        isync();
 238
 239        /* Enable Time Base & Decrementer ( so we will have udelay() )*/
 240        setbits_be32(&im->sysconf.spcr, SPCR_TBEN);
 241
 242        /* System General Purpose Register */
 243#ifdef CONFIG_SYS_SICRH
 244#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC8313)
 245        /* regarding to MPC34x manual rev.1 bits 28..29 must be preserved */
 246        __raw_writel((im->sysconf.sicrh & 0x0000000C) | CONFIG_SYS_SICRH,
 247                     &im->sysconf.sicrh);
 248#else
 249        __raw_writel(CONFIG_SYS_SICRH, &im->sysconf.sicrh);
 250#endif
 251#endif
 252#ifdef CONFIG_SYS_SICRL
 253        __raw_writel(CONFIG_SYS_SICRL, &im->sysconf.sicrl);
 254#endif
 255#ifdef CONFIG_SYS_GPR1
 256        __raw_writel(CONFIG_SYS_GPR1, &im->sysconf.gpr1);
 257#endif
 258#ifdef CONFIG_SYS_DDRCDR /* DDR control driver register */
 259        __raw_writel(CONFIG_SYS_DDRCDR, &im->sysconf.ddrcdr);
 260#endif
 261#ifdef CONFIG_SYS_OBIR /* Output buffer impedance register */
 262        __raw_writel(CONFIG_SYS_OBIR, &im->sysconf.obir);
 263#endif
 264
 265#ifdef CONFIG_QE
 266        /* Config QE ioports */
 267        config_qe_ioports();
 268#endif
 269        /* Set up preliminary BR/OR regs */
 270        init_early_memctl_regs();
 271
 272        /* Local Access window setup */
 273#if defined(CONFIG_SYS_LBLAWBAR0_PRELIM) && defined(CONFIG_SYS_LBLAWAR0_PRELIM)
 274        im->sysconf.lblaw[0].bar = CONFIG_SYS_LBLAWBAR0_PRELIM;
 275        im->sysconf.lblaw[0].ar = CONFIG_SYS_LBLAWAR0_PRELIM;
 276#else
 277#error  CONFIG_SYS_LBLAWBAR0_PRELIM & CONFIG_SYS_LBLAWAR0_PRELIM must be defined
 278#endif
 279
 280#if defined(CONFIG_SYS_LBLAWBAR1_PRELIM) && defined(CONFIG_SYS_LBLAWAR1_PRELIM)
 281        im->sysconf.lblaw[1].bar = CONFIG_SYS_LBLAWBAR1_PRELIM;
 282        im->sysconf.lblaw[1].ar = CONFIG_SYS_LBLAWAR1_PRELIM;
 283#endif
 284#if defined(CONFIG_SYS_LBLAWBAR2_PRELIM) && defined(CONFIG_SYS_LBLAWAR2_PRELIM)
 285        im->sysconf.lblaw[2].bar = CONFIG_SYS_LBLAWBAR2_PRELIM;
 286        im->sysconf.lblaw[2].ar = CONFIG_SYS_LBLAWAR2_PRELIM;
 287#endif
 288#if defined(CONFIG_SYS_LBLAWBAR3_PRELIM) && defined(CONFIG_SYS_LBLAWAR3_PRELIM)
 289        im->sysconf.lblaw[3].bar = CONFIG_SYS_LBLAWBAR3_PRELIM;
 290        im->sysconf.lblaw[3].ar = CONFIG_SYS_LBLAWAR3_PRELIM;
 291#endif
 292#if defined(CONFIG_SYS_LBLAWBAR4_PRELIM) && defined(CONFIG_SYS_LBLAWAR4_PRELIM)
 293        im->sysconf.lblaw[4].bar = CONFIG_SYS_LBLAWBAR4_PRELIM;
 294        im->sysconf.lblaw[4].ar = CONFIG_SYS_LBLAWAR4_PRELIM;
 295#endif
 296#if defined(CONFIG_SYS_LBLAWBAR5_PRELIM) && defined(CONFIG_SYS_LBLAWAR5_PRELIM)
 297        im->sysconf.lblaw[5].bar = CONFIG_SYS_LBLAWBAR5_PRELIM;
 298        im->sysconf.lblaw[5].ar = CONFIG_SYS_LBLAWAR5_PRELIM;
 299#endif
 300#if defined(CONFIG_SYS_LBLAWBAR6_PRELIM) && defined(CONFIG_SYS_LBLAWAR6_PRELIM)
 301        im->sysconf.lblaw[6].bar = CONFIG_SYS_LBLAWBAR6_PRELIM;
 302        im->sysconf.lblaw[6].ar = CONFIG_SYS_LBLAWAR6_PRELIM;
 303#endif
 304#if defined(CONFIG_SYS_LBLAWBAR7_PRELIM) && defined(CONFIG_SYS_LBLAWAR7_PRELIM)
 305        im->sysconf.lblaw[7].bar = CONFIG_SYS_LBLAWBAR7_PRELIM;
 306        im->sysconf.lblaw[7].ar = CONFIG_SYS_LBLAWAR7_PRELIM;
 307#endif
 308#ifdef CONFIG_SYS_GPIO1_PRELIM
 309        im->gpio[0].dat = CONFIG_SYS_GPIO1_DAT;
 310        im->gpio[0].dir = CONFIG_SYS_GPIO1_DIR;
 311#endif
 312#ifdef CONFIG_SYS_GPIO2_PRELIM
 313        im->gpio[1].dat = CONFIG_SYS_GPIO2_DAT;
 314        im->gpio[1].dir = CONFIG_SYS_GPIO2_DIR;
 315#endif
 316#if defined(CONFIG_USB_EHCI_FSL) && defined(CONFIG_MPC831x)
 317        uint32_t temp;
 318        struct usb_ehci *ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
 319
 320        /* Configure interface. */
 321        setbits_be32(&ehci->control, REFSEL_16MHZ | UTMI_PHY_EN);
 322
 323        /* Wait for clock to stabilize */
 324        do {
 325                temp = __raw_readl(&ehci->control);
 326                udelay(1000);
 327        } while (!(temp & PHY_CLK_VALID));
 328#endif
 329}
 330
 331int cpu_init_r (void)
 332{
 333#ifdef CONFIG_QE
 334        uint qe_base = CONFIG_SYS_IMMR + 0x00100000; /* QE immr base */
 335
 336        qe_init(qe_base);
 337        qe_reset();
 338#endif
 339        return 0;
 340}
 341
 342/*
 343 * Print out the bus arbiter event
 344 */
 345#if defined(CONFIG_DISPLAY_AER_FULL)
 346static int print_83xx_arb_event(int force)
 347{
 348        static char* event[] = {
 349                "Address Time Out",
 350                "Data Time Out",
 351                "Address Only Transfer Type",
 352                "External Control Word Transfer Type",
 353                "Reserved Transfer Type",
 354                "Transfer Error",
 355                "reserved",
 356                "reserved"
 357        };
 358        static char* master[] = {
 359                "e300 Core Data Transaction",
 360                "reserved",
 361                "e300 Core Instruction Fetch",
 362                "reserved",
 363                "TSEC1",
 364                "TSEC2",
 365                "USB MPH",
 366                "USB DR",
 367                "Encryption Core",
 368                "I2C Boot Sequencer",
 369                "JTAG",
 370                "reserved",
 371                "eSDHC",
 372                "PCI1",
 373                "PCI2",
 374                "DMA",
 375                "QUICC Engine 00",
 376                "QUICC Engine 01",
 377                "QUICC Engine 10",
 378                "QUICC Engine 11",
 379                "reserved",
 380                "reserved",
 381                "reserved",
 382                "reserved",
 383                "SATA1",
 384                "SATA2",
 385                "SATA3",
 386                "SATA4",
 387                "reserved",
 388                "PCI Express 1",
 389                "PCI Express 2",
 390                "TDM-DMAC"
 391        };
 392        static char *transfer[] = {
 393                "Address-only, Clean Block",
 394                "Address-only, lwarx reservation set",
 395                "Single-beat or Burst write",
 396                "reserved",
 397                "Address-only, Flush Block",
 398                "reserved",
 399                "Burst write",
 400                "reserved",
 401                "Address-only, sync",
 402                "Address-only, tlbsync",
 403                "Single-beat or Burst read",
 404                "Single-beat or Burst read",
 405                "Address-only, Kill Block",
 406                "Address-only, icbi",
 407                "Burst read",
 408                "reserved",
 409                "Address-only, eieio",
 410                "reserved",
 411                "Single-beat write",
 412                "reserved",
 413                "ecowx - Illegal single-beat write",
 414                "reserved",
 415                "reserved",
 416                "reserved",
 417                "Address-only, TLB Invalidate",
 418                "reserved",
 419                "Single-beat or Burst read",
 420                "reserved",
 421                "eciwx - Illegal single-beat read",
 422                "reserved",
 423                "Burst read",
 424                "reserved"
 425        };
 426
 427        int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT)
 428                    >> AEATR_EVENT_SHIFT;
 429        int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID)
 430                      >> AEATR_MSTR_ID_SHIFT;
 431        int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST)
 432                   >> AEATR_TBST_SHIFT;
 433        int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE)
 434                    >> AEATR_TSIZE_SHIFT;
 435        int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE)
 436                    >> AEATR_TTYPE_SHIFT;
 437
 438        if (!force && !gd->arch.arbiter_event_address)
 439                return 0;
 440
 441        puts("Arbiter Event Status:\n");
 442        printf("       Event Address: 0x%08lX\n",
 443               gd->arch.arbiter_event_address);
 444        printf("       Event Type:    0x%1x  = %s\n", etype, event[etype]);
 445        printf("       Master ID:     0x%02x = %s\n", mstr_id, master[mstr_id]);
 446        printf("       Transfer Size: 0x%1x  = %d bytes\n", (tbst<<3) | tsize,
 447                                tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize);
 448        printf("       Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]);
 449
 450        return gd->arch.arbiter_event_address;
 451}
 452
 453#elif defined(CONFIG_DISPLAY_AER_BRIEF)
 454
 455static int print_83xx_arb_event(int force)
 456{
 457        if (!force && !gd->arch.arbiter_event_address)
 458                return 0;
 459
 460        printf("Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
 461                gd->arch.arbiter_event_attributes,
 462                gd->arch.arbiter_event_address);
 463
 464        return gd->arch.arbiter_event_address;
 465}
 466#endif /* CONFIG_DISPLAY_AER_xxxx */
 467
 468/*
 469 * Figure out the cause of the reset
 470 */
 471int prt_83xx_rsr(void)
 472{
 473        static struct {
 474                ulong mask;
 475                char *desc;
 476        } bits[] = {
 477                {
 478                RSR_SWSR, "Software Soft"}, {
 479                RSR_SWHR, "Software Hard"}, {
 480                RSR_JSRS, "JTAG Soft"}, {
 481                RSR_CSHR, "Check Stop"}, {
 482                RSR_SWRS, "Software Watchdog"}, {
 483                RSR_BMRS, "Bus Monitor"}, {
 484                RSR_SRS,  "External/Internal Soft"}, {
 485                RSR_HRS,  "External/Internal Hard"}
 486        };
 487        static int n = sizeof bits / sizeof bits[0];
 488        ulong rsr = gd->arch.reset_status;
 489        int i;
 490        char *sep;
 491
 492        puts("Reset Status:");
 493
 494        sep = " ";
 495        for (i = 0; i < n; i++)
 496                if (rsr & bits[i].mask) {
 497                        printf("%s%s", sep, bits[i].desc);
 498                        sep = ", ";
 499                }
 500        puts("\n");
 501
 502#if defined(CONFIG_DISPLAY_AER_FULL) || defined(CONFIG_DISPLAY_AER_BRIEF)
 503        print_83xx_arb_event(rsr & RSR_BMRS);
 504#endif
 505        puts("\n");
 506
 507        return 0;
 508}
 509