83xx: serdes setup routines
authorAnton Vorontsov <avorontsov@ru.mvista.com>
Mon, 24 Mar 2008 14:40:32 +0000 (17:40 +0300)
committerKim Phillips <kim.phillips@freescale.com>
Wed, 26 Mar 2008 00:16:45 +0000 (19:16 -0500)
This patch adds few routines to configure serdes on 837x targets.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
cpu/mpc83xx/Makefile
cpu/mpc83xx/serdes.c [new file with mode: 0644]
include/asm-ppc/fsl_serdes.h [new file with mode: 0644]

index 7ad7e3e..fcb6a52 100644 (file)
@@ -37,6 +37,7 @@ COBJS-y += interrupts.o
 COBJS-y += spd_sdram.o
 COBJS-y += ecc.o
 COBJS-$(CONFIG_QE) += qe_io.o
+COBJS-$(CONFIG_FSL_SERDES) += serdes.o
 COBJS-$(CONFIG_83XX_GENERIC_PCI) += pci.o
 COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
 
diff --git a/cpu/mpc83xx/serdes.c b/cpu/mpc83xx/serdes.c
new file mode 100644 (file)
index 0000000..020c4c8
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Freescale SerDes initialization routine
+ *
+ * Copyright (C) 2007 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2008 MontaVista Software, Inc. All rights reserved.
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_serdes.h>
+
+/* SerDes registers */
+#define FSL_SRDSCR0_OFFS               0x0
+#define FSL_SRDSCR0_DPP_1V2            0x00008800
+#define FSL_SRDSCR1_OFFS               0x4
+#define FSL_SRDSCR1_PLLBW              0x00000040
+#define FSL_SRDSCR2_OFFS               0x8
+#define FSL_SRDSCR2_VDD_1V2            0x00800000
+#define FSL_SRDSCR2_SEIC_MASK          0x00001c1c
+#define FSL_SRDSCR2_SEIC_SATA          0x00001414
+#define FSL_SRDSCR2_SEIC_PEX           0x00001010
+#define FSL_SRDSCR2_SEIC_SGMII         0x00000101
+#define FSL_SRDSCR3_OFFS               0xc
+#define FSL_SRDSCR3_KFR_SATA           0x10100000
+#define FSL_SRDSCR3_KPH_SATA           0x04040000
+#define FSL_SRDSCR3_SDFM_SATA_PEX      0x01010000
+#define FSL_SRDSCR3_SDTXL_SATA         0x00000505
+#define FSL_SRDSCR4_OFFS               0x10
+#define FSL_SRDSCR4_PROT_SATA          0x00000808
+#define FSL_SRDSCR4_PROT_PEX           0x00000101
+#define FSL_SRDSCR4_PROT_SGMII         0x00000505
+#define FSL_SRDSCR4_PLANE_X2           0x01000000
+#define FSL_SRDSRSTCTL_OFFS            0x20
+#define FSL_SRDSRSTCTL_RST             0x80000000
+#define FSL_SRDSRSTCTL_SATA_RESET      0xf
+
+void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd)
+{
+       void *regs = (void *)CFG_IMMR + offset;
+       u32 tmp;
+
+       /* 1.0V corevdd */
+       if (vdd) {
+               /* DPPE/DPPA = 0 */
+               tmp = in_be32(regs + FSL_SRDSCR0_OFFS);
+               tmp &= ~FSL_SRDSCR0_DPP_1V2;
+               out_be32(regs + FSL_SRDSCR0_OFFS, tmp);
+
+               /* VDD = 0 */
+               tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_VDD_1V2;
+               out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+       }
+
+       /* protocol specific configuration */
+       switch (proto) {
+       case FSL_SERDES_PROTO_SATA:
+               /* Set and clear reset bits */
+               tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+               tmp |= FSL_SRDSRSTCTL_SATA_RESET;
+               out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+               udelay(1000);
+               tmp &= ~FSL_SRDSRSTCTL_SATA_RESET;
+               out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+
+               /* Configure SRDSCR1 */
+               tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_PLLBW;
+               out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+               /* Configure SRDSCR2 */
+               tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+               tmp |= FSL_SRDSCR2_SEIC_SATA;
+               out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+               /* Configure SRDSCR3 */
+               tmp = FSL_SRDSCR3_KFR_SATA | FSL_SRDSCR3_KPH_SATA |
+                       FSL_SRDSCR3_SDFM_SATA_PEX |
+                       FSL_SRDSCR3_SDTXL_SATA;
+               out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+               /* Configure SRDSCR4 */
+               tmp = rfcks | FSL_SRDSCR4_PROT_SATA;
+               out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+               break;
+       case FSL_SERDES_PROTO_PEX:
+       case FSL_SERDES_PROTO_PEX_X2:
+               /* Configure SRDSCR1 */
+               tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+               tmp |= FSL_SRDSCR1_PLLBW;
+               out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+               /* Configure SRDSCR2 */
+               tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+               tmp |= FSL_SRDSCR2_SEIC_PEX;
+               out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+               /* Configure SRDSCR3 */
+               tmp = FSL_SRDSCR3_SDFM_SATA_PEX;
+               out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+               /* Configure SRDSCR4 */
+               tmp = rfcks | FSL_SRDSCR4_PROT_PEX;
+               if (proto == FSL_SERDES_PROTO_PEX_X2)
+                       tmp |= FSL_SRDSCR4_PLANE_X2;
+               out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+               break;
+       case FSL_SERDES_PROTO_SGMII:
+               /* Configure SRDSCR1 */
+               tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_PLLBW;
+               out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+               /* Configure SRDSCR2 */
+               tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+               tmp |= FSL_SRDSCR2_SEIC_SGMII;
+               out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+               /* Configure SRDSCR3 */
+               out_be32(regs + FSL_SRDSCR3_OFFS, 0);
+
+               /* Configure SRDSCR4 */
+               tmp = rfcks | FSL_SRDSCR4_PROT_SGMII;
+               out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+               break;
+       default:
+               return;
+       }
+
+       /* Do a software reset */
+       tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+       tmp |= FSL_SRDSRSTCTL_RST;
+       out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+}
diff --git a/include/asm-ppc/fsl_serdes.h b/include/asm-ppc/fsl_serdes.h
new file mode 100644 (file)
index 0000000..733f919
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __FSL_SERDES_H
+#define __FSL_SERDES_H
+
+#include <config.h>
+
+#define FSL_SERDES_CLK_100             0
+#define FSL_SERDES_CLK_125             1
+#define FSL_SERDES_CLK_150             3
+#define FSL_SERDES_PROTO_SATA          0
+#define FSL_SERDES_PROTO_PEX           1
+#define FSL_SERDES_PROTO_PEX_X2                2
+#define FSL_SERDES_PROTO_SGMII         3
+#define FSL_SERDES_VDD_1V              1
+
+#ifdef CONFIG_FSL_SERDES
+extern void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd);
+#else
+static void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd) {}
+#endif /* CONFIG_FSL_SERDES */
+
+#endif /* __FSL_SERDES_H */