summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
diff options
context:
space:
mode:
authorWang Huan <b18965@freescale.com>2014-09-05 13:52:34 +0800
committerYork Sun <yorksun@freescale.com>2014-09-08 10:30:32 -0700
commitd60a2099a20254b33a314895a4b5e6a21aebd135 (patch)
tree2fb79855edd6466a89c84cc4ce6210802aa75d06 /arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
parentd6c1ffc7d23f4fe4ae8c91101861055b8e1501b6 (diff)
arm: ls102xa: Add Freescale LS102xA SoC support
The QorIQ LS1 family is built on Layerscape architecture, the industry's first software-aware, core-agnostic networking architecture to offer unprecedented efficiency and scale. Freescale LS102xA is a set of SoCs combines two ARM Cortex-A7 cores that have been optimized for high reliability and pack the highest level of integration available for sub-3 W embedded communications processors with Layerscape architecture and with a comprehensive enablement model focused on ease of programmability. Signed-off-by: Alison Wang <alison.wang@freescale.com> Signed-off-by: Jason Jin <jason.jin@freescale.com> Signed-off-by: Jingchang Lu <jingchang.lu@freescale.com> Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
Diffstat (limited to 'arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c')
-rw-r--r--arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
new file mode 100644
index 0000000000..9b78acb25a
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include "fsl_ls1_serdes.h"
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+static u64 serdes1_prtcl_map;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+static u64 serdes2_prtcl_map;
+#endif
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ u64 ret = 0;
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ ret |= (1ULL << device) & serdes1_prtcl_map;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ ret |= (1ULL << device) & serdes2_prtcl_map;
+#endif
+
+ return !!ret;
+}
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ u32 cfg = in_be32(&gur->rcwsr[4]);
+ int i;
+
+ switch (sd) {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ case FSL_SRDS_1:
+ cfg &= RCWSR4_SRDS1_PRTCL_MASK;
+ cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT;
+ break;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ case FSL_SRDS_2:
+ cfg &= RCWSR4_SRDS2_PRTCL_MASK;
+ cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT;
+ break;
+#endif
+ default:
+ printf("invalid SerDes%d\n", sd);
+ break;
+ }
+ /* Is serdes enabled at all? */
+ if (unlikely(cfg == 0))
+ return -ENODEV;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_get_prtcl(sd, cfg, i) == device)
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ u64 serdes_prtcl_map = 0;
+ u32 cfg;
+ int lane;
+
+ cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
+ cfg >>= sd_prctl_shift;
+ printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+
+ if (!is_serdes_prtcl_valid(sd, cfg))
+ printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+
+ for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
+
+ serdes_prtcl_map |= (1ULL << lane_prtcl);
+ }
+
+ return serdes_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+#ifdef CONFIG_SYS_FSL_SRDS_1
+ serdes1_prtcl_map = serdes_init(FSL_SRDS_1,
+ CONFIG_SYS_FSL_SERDES_ADDR,
+ RCWSR4_SRDS1_PRTCL_MASK,
+ RCWSR4_SRDS1_PRTCL_SHIFT);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+ serdes2_prtcl_map = serdes_init(FSL_SRDS_2,
+ CONFIG_SYS_FSL_SERDES_ADDR +
+ FSL_SRDS_2 * 0x1000,
+ RCWSR4_SRDS2_PRTCL_MASK,
+ RCWSR4_SRDS2_PRTCL_SHIFT);
+#endif
+}
+
+const char *serdes_clock_to_string(u32 clock)
+{
+ switch (clock) {
+ case SRDS_PLLCR0_RFCK_SEL_100:
+ return "100";
+ case SRDS_PLLCR0_RFCK_SEL_125:
+ return "125";
+ default:
+ return "100";
+ }
+}