uboot/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2014 Freescale Semiconductor, Inc.
   4 */
   5
   6#include <common.h>
   7#include <asm/arch/fsl_serdes.h>
   8#include <asm/arch/immap_ls102xa.h>
   9#include <linux/errno.h>
  10#include <asm/io.h>
  11#include "fsl_ls1_serdes.h"
  12
  13#ifdef CONFIG_SYS_FSL_SRDS_1
  14static u64 serdes1_prtcl_map;
  15#endif
  16#ifdef CONFIG_SYS_FSL_SRDS_2
  17static u64 serdes2_prtcl_map;
  18#endif
  19
  20int is_serdes_configured(enum srds_prtcl device)
  21{
  22        u64 ret = 0;
  23
  24#ifdef CONFIG_SYS_FSL_SRDS_1
  25        if (!(serdes1_prtcl_map & (1ULL << NONE)))
  26                fsl_serdes_init();
  27
  28        ret |= (1ULL << device) & serdes1_prtcl_map;
  29#endif
  30#ifdef CONFIG_SYS_FSL_SRDS_2
  31        if (!(serdes2_prtcl_map & (1ULL << NONE)))
  32                fsl_serdes_init();
  33
  34        ret |= (1ULL << device) & serdes2_prtcl_map;
  35#endif
  36
  37        return !!ret;
  38}
  39
  40int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
  41{
  42        struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR);
  43        u32 cfg = in_be32(&gur->rcwsr[4]);
  44        int i;
  45
  46        switch (sd) {
  47#ifdef CONFIG_SYS_FSL_SRDS_1
  48        case FSL_SRDS_1:
  49                cfg &= RCWSR4_SRDS1_PRTCL_MASK;
  50                cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT;
  51                break;
  52#endif
  53#ifdef CONFIG_SYS_FSL_SRDS_2
  54        case FSL_SRDS_2:
  55                cfg &= RCWSR4_SRDS2_PRTCL_MASK;
  56                cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT;
  57                break;
  58#endif
  59        default:
  60                printf("invalid SerDes%d\n", sd);
  61                break;
  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
  75u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
  76{
  77        struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR);
  78        u64 serdes_prtcl_map = 0;
  79        u32 cfg;
  80        int lane;
  81
  82        cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
  83        cfg >>= sd_prctl_shift;
  84        printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
  85
  86        if (!is_serdes_prtcl_valid(sd, cfg))
  87                printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
  88
  89        for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
  90                enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
  91
  92                serdes_prtcl_map |= (1ULL << lane_prtcl);
  93        }
  94
  95        /* Set the first bit to indicate serdes has been initialized */
  96        serdes_prtcl_map |= (1ULL << NONE);
  97
  98        return serdes_prtcl_map;
  99}
 100
 101void fsl_serdes_init(void)
 102{
 103#ifdef CONFIG_SYS_FSL_SRDS_1
 104        if (!(serdes1_prtcl_map & (1ULL << NONE)))
 105                serdes1_prtcl_map = serdes_init(FSL_SRDS_1,
 106                                        CFG_SYS_FSL_SERDES_ADDR,
 107                                        RCWSR4_SRDS1_PRTCL_MASK,
 108                                        RCWSR4_SRDS1_PRTCL_SHIFT);
 109#endif
 110#ifdef CONFIG_SYS_FSL_SRDS_2
 111        if (!(serdes2_prtcl_map & (1ULL << NONE)))
 112                serdes2_prtcl_map = serdes_init(FSL_SRDS_2,
 113                                        CFG_SYS_FSL_SERDES_ADDR +
 114                                        FSL_SRDS_2 * 0x1000,
 115                                        RCWSR4_SRDS2_PRTCL_MASK,
 116                                        RCWSR4_SRDS2_PRTCL_SHIFT);
 117#endif
 118}
 119
 120const char *serdes_clock_to_string(u32 clock)
 121{
 122        switch (clock) {
 123        case SRDS_PLLCR0_RFCK_SEL_100:
 124                return "100";
 125        case SRDS_PLLCR0_RFCK_SEL_125:
 126                return "125";
 127        default:
 128                return "100";
 129        }
 130}
 131