uboot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2015 Freescale Semiconductor, Inc.
   4 */
   5
   6#include <common.h>
   7#include <asm/io.h>
   8#include <linux/errno.h>
   9#include <asm/arch/fsl_serdes.h>
  10#include <asm/arch/soc.h>
  11
  12#ifdef CONFIG_SYS_FSL_SRDS_1
  13static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
  14#endif
  15#ifdef CONFIG_SYS_FSL_SRDS_2
  16static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
  17#endif
  18
  19int is_serdes_configured(enum srds_prtcl device)
  20{
  21        int ret = 0;
  22
  23#ifdef CONFIG_SYS_FSL_SRDS_1
  24        if (!serdes1_prtcl_map[NONE])
  25                fsl_serdes_init();
  26
  27        ret |= serdes1_prtcl_map[device];
  28#endif
  29#ifdef CONFIG_SYS_FSL_SRDS_2
  30        if (!serdes2_prtcl_map[NONE])
  31                fsl_serdes_init();
  32
  33        ret |= serdes2_prtcl_map[device];
  34#endif
  35
  36        return !!ret;
  37}
  38
  39int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
  40{
  41        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  42        u32 cfg = gur_in32(&gur->rcwsr[4]);
  43        int i;
  44
  45        switch (sd) {
  46#ifdef CONFIG_SYS_FSL_SRDS_1
  47        case FSL_SRDS_1:
  48                cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
  49                cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
  50                break;
  51#endif
  52#ifdef CONFIG_SYS_FSL_SRDS_2
  53        case FSL_SRDS_2:
  54                cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
  55                cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
  56                break;
  57#endif
  58        default:
  59                printf("invalid SerDes%d\n", sd);
  60                break;
  61        }
  62
  63        /* Is serdes enabled at all? */
  64        if (unlikely(cfg == 0))
  65                return -ENODEV;
  66
  67        for (i = 0; i < SRDS_MAX_LANES; i++) {
  68                if (serdes_get_prtcl(sd, cfg, i) == device)
  69                        return i;
  70        }
  71
  72        return -ENODEV;
  73}
  74
  75int get_serdes_protocol(void)
  76{
  77        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  78        u32 cfg = gur_in32(&gur->rcwsr[4]) &
  79                          FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
  80        cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
  81
  82        return cfg;
  83}
  84
  85const char *serdes_clock_to_string(u32 clock)
  86{
  87        switch (clock) {
  88        case SRDS_PLLCR0_RFCK_SEL_100:
  89                return "100";
  90        case SRDS_PLLCR0_RFCK_SEL_125:
  91                return "125";
  92        case SRDS_PLLCR0_RFCK_SEL_156_25:
  93                return "156.25";
  94        default:
  95                return "100";
  96        }
  97}
  98
  99void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
 100                 u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
 101{
 102        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
 103        u32 cfg;
 104        int lane;
 105
 106        if (serdes_prtcl_map[NONE])
 107                return;
 108
 109        memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
 110
 111        cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
 112        cfg >>= sd_prctl_shift;
 113        printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
 114
 115        if (!is_serdes_prtcl_valid(sd, cfg))
 116                printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
 117
 118        for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
 119                enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
 120
 121                if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
 122                        debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
 123                else
 124                        serdes_prtcl_map[lane_prtcl] = 1;
 125        }
 126
 127        /* Set the first element to indicate serdes has been initialized */
 128        serdes_prtcl_map[NONE] = 1;
 129}
 130
 131__weak int get_serdes_volt(void)
 132{
 133        return -1;
 134}
 135
 136__weak int set_serdes_volt(int svdd)
 137{
 138        return -1;
 139}
 140
 141int setup_serdes_volt(u32 svdd)
 142{
 143        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
 144        struct ccsr_serdes *serdes1_base;
 145#ifdef CONFIG_SYS_FSL_SRDS_2
 146        struct ccsr_serdes *serdes2_base;
 147#endif
 148        u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]);
 149        u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]);
 150        u32 cfg_tmp, reg = 0;
 151        int svdd_cur, svdd_tar;
 152        int ret;
 153        int i;
 154
 155        /* Only support switch SVDD to 900mV/1000mV */
 156        if (svdd != 900 && svdd != 1000)
 157                return -EINVAL;
 158
 159        svdd_tar = svdd;
 160        svdd_cur = get_serdes_volt();
 161        if (svdd_cur < 0)
 162                return -EINVAL;
 163
 164        debug("%s: current SVDD: %dmV; target SVDD: %dmV\n",
 165              __func__, svdd_cur, svdd_tar);
 166        if (svdd_cur == svdd_tar)
 167                return 0;
 168
 169        serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR;
 170#ifdef CONFIG_SYS_FSL_SRDS_2
 171        serdes2_base = (void *)serdes1_base + 0x10000;
 172#endif
 173
 174        /* Put the all enabled lanes in reset */
 175#ifdef CONFIG_SYS_FSL_SRDS_1
 176        cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
 177        cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
 178
 179        for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
 180                reg = in_be32(&serdes1_base->lane[i].gcr0);
 181                reg &= 0xFF9FFFFF;
 182                out_be32(&serdes1_base->lane[i].gcr0, reg);
 183        }
 184#endif
 185#ifdef CONFIG_SYS_FSL_SRDS_2
 186        cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
 187        cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
 188
 189        for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
 190                reg = in_be32(&serdes2_base->lane[i].gcr0);
 191                reg &= 0xFF9FFFFF;
 192                out_be32(&serdes2_base->lane[i].gcr0, reg);
 193        }
 194#endif
 195
 196        /* Put the all enabled PLL in reset */
 197#ifdef CONFIG_SYS_FSL_SRDS_1
 198        cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
 199        for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
 200                reg = in_be32(&serdes1_base->bank[i].rstctl);
 201                reg &= 0xFFFFFFBF;
 202                reg |= 0x10000000;
 203                out_be32(&serdes1_base->bank[i].rstctl, reg);
 204                udelay(1);
 205
 206                reg = in_be32(&serdes1_base->bank[i].rstctl);
 207                reg &= 0xFFFFFF1F;
 208                out_be32(&serdes1_base->bank[i].rstctl, reg);
 209        }
 210        udelay(1);
 211#endif
 212
 213#ifdef CONFIG_SYS_FSL_SRDS_2
 214        cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
 215        for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
 216                reg = in_be32(&serdes2_base->bank[i].rstctl);
 217                reg &= 0xFFFFFFBF;
 218                reg |= 0x10000000;
 219                out_be32(&serdes2_base->bank[i].rstctl, reg);
 220                udelay(1);
 221
 222                reg = in_be32(&serdes2_base->bank[i].rstctl);
 223                reg &= 0xFFFFFF1F;
 224                out_be32(&serdes2_base->bank[i].rstctl, reg);
 225        }
 226        udelay(1);
 227#endif
 228
 229        /* Put the Rx/Tx calibration into reset */
 230#ifdef CONFIG_SYS_FSL_SRDS_1
 231        reg = in_be32(&serdes1_base->srdstcalcr);
 232        reg &= 0xF7FFFFFF;
 233        out_be32(&serdes1_base->srdstcalcr, reg);
 234        reg = in_be32(&serdes1_base->srdsrcalcr);
 235        reg &= 0xF7FFFFFF;
 236        out_be32(&serdes1_base->srdsrcalcr, reg);
 237
 238#endif
 239#ifdef CONFIG_SYS_FSL_SRDS_2
 240        reg = in_be32(&serdes2_base->srdstcalcr);
 241        reg &= 0xF7FFFFFF;
 242        out_be32(&serdes2_base->srdstcalcr, reg);
 243        reg = in_be32(&serdes2_base->srdsrcalcr);
 244        reg &= 0xF7FFFFFF;
 245        out_be32(&serdes2_base->srdsrcalcr, reg);
 246#endif
 247
 248        /*
 249         * If SVDD set failed, will not return directly, so that the
 250         * serdes lanes can complete reseting.
 251         */
 252        ret = set_serdes_volt(svdd_tar);
 253        if (ret)
 254                printf("%s: Failed to set SVDD\n", __func__);
 255
 256        /* Wait for SVDD to stabilize */
 257        udelay(100);
 258
 259        /* For each PLL that’s not disabled via RCW */
 260#ifdef CONFIG_SYS_FSL_SRDS_1
 261        cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
 262        for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
 263                reg = in_be32(&serdes1_base->bank[i].rstctl);
 264                reg |= 0x00000020;
 265                out_be32(&serdes1_base->bank[i].rstctl, reg);
 266                udelay(1);
 267
 268                reg = in_be32(&serdes1_base->bank[i].rstctl);
 269                reg |= 0x00000080;
 270                out_be32(&serdes1_base->bank[i].rstctl, reg);
 271
 272                /* Take the Rx/Tx calibration out of reset */
 273                if (!(cfg_tmp == 0x3 && i == 1)) {
 274                        udelay(1);
 275                        reg = in_be32(&serdes1_base->srdstcalcr);
 276                        reg |= 0x08000000;
 277                        out_be32(&serdes1_base->srdstcalcr, reg);
 278                        reg = in_be32(&serdes1_base->srdsrcalcr);
 279                        reg |= 0x08000000;
 280                        out_be32(&serdes1_base->srdsrcalcr, reg);
 281                }
 282        }
 283        udelay(1);
 284#endif
 285
 286#ifdef CONFIG_SYS_FSL_SRDS_2
 287        cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
 288        for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
 289                reg = in_be32(&serdes2_base->bank[i].rstctl);
 290                reg |= 0x00000020;
 291                out_be32(&serdes2_base->bank[i].rstctl, reg);
 292                udelay(1);
 293
 294                reg = in_be32(&serdes2_base->bank[i].rstctl);
 295                reg |= 0x00000080;
 296                out_be32(&serdes2_base->bank[i].rstctl, reg);
 297
 298                /* Take the Rx/Tx calibration out of reset */
 299                if (!(cfg_tmp == 0x3 && i == 1)) {
 300                        udelay(1);
 301                        reg = in_be32(&serdes2_base->srdstcalcr);
 302                        reg |= 0x08000000;
 303                        out_be32(&serdes2_base->srdstcalcr, reg);
 304                        reg = in_be32(&serdes2_base->srdsrcalcr);
 305                        reg |= 0x08000000;
 306                        out_be32(&serdes2_base->srdsrcalcr, reg);
 307                }
 308        }
 309        udelay(1);
 310
 311#endif
 312
 313        /* Wait for at lesat 625us to ensure the PLLs being reset are locked */
 314        udelay(800);
 315
 316#ifdef CONFIG_SYS_FSL_SRDS_1
 317        cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
 318        for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
 319                /* if the PLL is not locked, set RST_ERR */
 320                reg = in_be32(&serdes1_base->bank[i].pllcr0);
 321                if (!((reg >> 23) & 0x1)) {
 322                        reg = in_be32(&serdes1_base->bank[i].rstctl);
 323                        reg |= 0x20000000;
 324                        out_be32(&serdes1_base->bank[i].rstctl, reg);
 325                } else {
 326                        udelay(1);
 327                        reg = in_be32(&serdes1_base->bank[i].rstctl);
 328                        reg &= 0xFFFFFFEF;
 329                        reg |= 0x00000040;
 330                        out_be32(&serdes1_base->bank[i].rstctl, reg);
 331                        udelay(1);
 332                }
 333        }
 334#endif
 335
 336#ifdef CONFIG_SYS_FSL_SRDS_2
 337        cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
 338        for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
 339                reg = in_be32(&serdes2_base->bank[i].pllcr0);
 340                if (!((reg >> 23) & 0x1)) {
 341                        reg = in_be32(&serdes2_base->bank[i].rstctl);
 342                        reg |= 0x20000000;
 343                        out_be32(&serdes2_base->bank[i].rstctl, reg);
 344                } else {
 345                        udelay(1);
 346                        reg = in_be32(&serdes2_base->bank[i].rstctl);
 347                        reg &= 0xFFFFFFEF;
 348                        reg |= 0x00000040;
 349                        out_be32(&serdes2_base->bank[i].rstctl, reg);
 350                        udelay(1);
 351                }
 352        }
 353#endif
 354
 355        /* Take the all enabled lanes out of reset */
 356#ifdef CONFIG_SYS_FSL_SRDS_1
 357        cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
 358        cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
 359
 360        for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
 361                reg = in_be32(&serdes1_base->lane[i].gcr0);
 362                reg |= 0x00600000;
 363                out_be32(&serdes1_base->lane[i].gcr0, reg);
 364        }
 365#endif
 366#ifdef CONFIG_SYS_FSL_SRDS_2
 367        cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
 368        cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
 369
 370        for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
 371                reg = in_be32(&serdes2_base->lane[i].gcr0);
 372                reg |= 0x00600000;
 373                out_be32(&serdes2_base->lane[i].gcr0, reg);
 374        }
 375#endif
 376        /* For each PLL being reset, and achieved PLL lock set RST_DONE */
 377#ifdef CONFIG_SYS_FSL_SRDS_1
 378        cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
 379        for (i = 0; i < 2; i++) {
 380                reg = in_be32(&serdes1_base->bank[i].pllcr0);
 381                if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
 382                        reg = in_be32(&serdes1_base->bank[i].rstctl);
 383                        reg |= 0x40000000;
 384                        out_be32(&serdes1_base->bank[i].rstctl, reg);
 385                }
 386        }
 387#endif
 388#ifdef CONFIG_SYS_FSL_SRDS_2
 389        cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
 390        for (i = 0; i < 2; i++) {
 391                reg = in_be32(&serdes2_base->bank[i].pllcr0);
 392                if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
 393                        reg = in_be32(&serdes2_base->bank[i].rstctl);
 394                        reg |= 0x40000000;
 395                        out_be32(&serdes2_base->bank[i].rstctl, reg);
 396                }
 397        }
 398#endif
 399
 400        return ret;
 401}
 402
 403void fsl_serdes_init(void)
 404{
 405#ifdef CONFIG_SYS_FSL_SRDS_1
 406        serdes_init(FSL_SRDS_1,
 407                    CONFIG_SYS_FSL_SERDES_ADDR,
 408                    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
 409                    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
 410                    serdes1_prtcl_map);
 411#endif
 412#ifdef CONFIG_SYS_FSL_SRDS_2
 413        serdes_init(FSL_SRDS_2,
 414                    CONFIG_SYS_FSL_SERDES_ADDR,
 415                    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK,
 416                    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT,
 417                    serdes2_prtcl_map);
 418#endif
 419}
 420