mpc85xx: Add support for the MPC8536
authorKumar Gala <galak@kernel.crashing.org>
Tue, 12 Aug 2008 16:14:19 +0000 (11:14 -0500)
committerKumar Gala <galak@kernel.crashing.org>
Wed, 27 Aug 2008 16:43:54 +0000 (11:43 -0500)
The MPC8536 Adds SDHC and SATA controllers to the PQ3 family.  We
also have SERDES init code for the 8536.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
Signed-off-by: Dejan Minic <minic@freescale.com>
Signed-off-by: Jason Jin <Jason.jin@freescale.com>
Signed-off-by: Dave Liu <daveliu@freescale.com>
cpu/mpc85xx/Makefile
cpu/mpc85xx/cpu.c
cpu/mpc85xx/cpu_init.c
cpu/mpc85xx/mpc8536_serdes.c [new file with mode: 0644]
cpu/mpc85xx/speed.c
drivers/misc/fsl_law.c
include/asm-ppc/global_data.h
include/asm-ppc/immap_85xx.h
include/asm-ppc/processor.h
include/pci_ids.h

index 80b80ff..627e61b 100644 (file)
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_MPC8544) += ddr-gen2.o
 COBJS-$(CONFIG_MPC8572) += ddr-gen3.o
 COBJS-$(CONFIG_MPC8536) += ddr-gen3.o
 
+COBJS-$(CONFIG_MPC8536) += mpc8536_serdes.o
 COBJS  = traps.o cpu.o cpu_init.o speed.o interrupts.o tlb.o \
          pci.o serial_scc.o commproc.o ether_fcc.o qe_io.o \
          $(COBJS-y)
index 5c2231d..2fe3cea 100644 (file)
@@ -36,6 +36,8 @@ DECLARE_GLOBAL_DATA_PTR;
 struct cpu_type cpu_type_list [] = {
        CPU_TYPE_ENTRY(8533, 8533),
        CPU_TYPE_ENTRY(8533, 8533_E),
+       CPU_TYPE_ENTRY(8536, 8536),
+       CPU_TYPE_ENTRY(8536, 8536_E),
        CPU_TYPE_ENTRY(8540, 8540),
        CPU_TYPE_ENTRY(8541, 8541),
        CPU_TYPE_ENTRY(8541, 8541_E),
@@ -89,6 +91,9 @@ int checkcpu (void)
        svr = get_svr();
        ver = SVR_SOC_VER(svr);
        major = SVR_MAJ(svr);
+#ifdef CONFIG_MPC8536
+       major &= 0x7; /* the msb of this nibble is a mfg code */
+#endif
        minor = SVR_MIN(svr);
 
        puts("CPU:   ");
@@ -154,7 +159,8 @@ int checkcpu (void)
 #endif
        clkdiv = lcrr & 0x0f;
        if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
-#if defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || defined(CONFIG_MPC8572)
+#if defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || \
+    defined(CONFIG_MPC8572) || defined(CONFIG_MPC8536)
                /*
                 * Yes, the entire PQ38 family use the same
                 * bit-representation for twice the clock divider values.
index 4feb751..783c5ba 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_MPC8536
+extern void fsl_serdes_init(void);
+#endif
+
 #ifdef CONFIG_QE
 extern qe_iop_conf_t qe_iop_conf_tab[];
 extern void qe_config_iopin(u8 port, u8 pin, int dir,
@@ -240,6 +244,9 @@ void cpu_init_f (void)
        /* Config QE ioports */
        config_qe_ioports();
 #endif
+#if defined(CONFIG_MPC8536)
+       fsl_serdes_init();
+#endif
 
 }
 
diff --git a/cpu/mpc85xx/mpc8536_serdes.c b/cpu/mpc85xx/mpc8536_serdes.c
new file mode 100644 (file)
index 0000000..ae091e6
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008 Freescale Semicondutor, Inc. All rights reserved.
+ *     Dave Liu <daveliu@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/immap_85xx.h>
+
+/* PORDEVSR register */
+#define GUTS_PORDEVSR_OFFS             0xc
+#define GUTS_PORDEVSR_SERDES2_IO_SEL   0x38000000
+#define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT     27
+
+/* SerDes CR0 register */
+#define        FSL_SRDSCR0_OFFS        0x0
+#define FSL_SRDSCR0_TXEQA_MASK 0x00007000
+#define FSL_SRDSCR0_TXEQA_SGMII        0x00004000
+#define FSL_SRDSCR0_TXEQA_SATA 0x00001000
+#define FSL_SRDSCR0_TXEQE_MASK 0x00000700
+#define FSL_SRDSCR0_TXEQE_SGMII        0x00000400
+#define FSL_SRDSCR0_TXEQE_SATA 0x00000100
+
+/* SerDes CR1 register */
+#define FSL_SRDSCR1_OFFS       0x4
+#define FSL_SRDSCR1_LANEA_MASK 0x80200000
+#define FSL_SRDSCR1_LANEA_OFF  0x80200000
+#define FSL_SRDSCR1_LANEE_MASK 0x08020000
+#define FSL_SRDSCR1_LANEE_OFF  0x08020000
+
+/* SerDes CR2 register */
+#define FSL_SRDSCR2_OFFS       0x8
+#define FSL_SRDSCR2_EICA_MASK  0x00001f00
+#define FSL_SRDSCR2_EICA_SGMII 0x00000400
+#define FSL_SRDSCR2_EICA_SATA  0x00001400
+#define FSL_SRDSCR2_EICE_MASK  0x0000001f
+#define FSL_SRDSCR2_EICE_SGMII 0x00000004
+#define FSL_SRDSCR2_EICE_SATA  0x00000014
+
+/* SerDes CR3 register */
+#define FSL_SRDSCR3_OFFS       0xc
+#define FSL_SRDSCR3_LANEA_MASK 0x3f000700
+#define FSL_SRDSCR3_LANEA_SGMII        0x00000000
+#define FSL_SRDSCR3_LANEA_SATA 0x15000500
+#define FSL_SRDSCR3_LANEE_MASK 0x003f0007
+#define FSL_SRDSCR3_LANEE_SGMII        0x00000000
+#define FSL_SRDSCR3_LANEE_SATA 0x00150005
+
+void fsl_serdes_init(void)
+{
+       void *guts = (void *)(CFG_MPC85xx_GUTS_ADDR);
+       void *sd = (void *)CFG_MPC85xx_SERDES2_ADDR;
+       u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
+       u32 srds2_io_sel;
+       u32 tmp;
+
+       /* parse the SRDS2_IO_SEL of PORDEVSR */
+       srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
+                      >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
+
+       switch (srds2_io_sel) {
+       case 1: /* Lane A - SATA1, Lane E - SATA2 */
+               /* CR 0 */
+               tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+               tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+               tmp |= FSL_SRDSCR0_TXEQA_SATA;
+               tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+               tmp |= FSL_SRDSCR0_TXEQE_SATA;
+               out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+               /* CR 1 */
+               tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+               tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+               out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+               /* CR 2 */
+               tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_EICA_MASK;
+               tmp |= FSL_SRDSCR2_EICA_SATA;
+               tmp &= ~FSL_SRDSCR2_EICE_MASK;
+               tmp |= FSL_SRDSCR2_EICE_SATA;
+               out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+               /* CR 3 */
+               tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+               tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+               tmp |= FSL_SRDSCR3_LANEA_SATA;
+               tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+               tmp |= FSL_SRDSCR3_LANEE_SATA;
+               out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+               break;
+       case 3: /* Lane A - SATA1, Lane E - disabled */
+               /* CR 0 */
+               tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+               tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+               tmp |= FSL_SRDSCR0_TXEQA_SATA;
+               out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+               /* CR 1 */
+               tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+               tmp |= FSL_SRDSCR1_LANEE_OFF;
+               out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+               /* CR 2 */
+               tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_EICA_MASK;
+               tmp |= FSL_SRDSCR2_EICA_SATA;
+               out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+               /* CR 3 */
+               tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+               tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+               tmp |= FSL_SRDSCR3_LANEA_SATA;
+               out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+               break;
+       case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
+               /* CR 0 */
+               tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+               tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+               tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+               tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+               tmp |= FSL_SRDSCR0_TXEQE_SGMII;
+               out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+               /* CR 1 */
+               tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+               tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+               out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+               /* CR 2 */
+               tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_EICA_MASK;
+               tmp |= FSL_SRDSCR2_EICA_SGMII;
+               tmp &= ~FSL_SRDSCR2_EICE_MASK;
+               tmp |= FSL_SRDSCR2_EICE_SGMII;
+               out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+               /* CR 3 */
+               tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+               tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+               tmp |= FSL_SRDSCR3_LANEA_SGMII;
+               tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+               tmp |= FSL_SRDSCR3_LANEE_SGMII;
+               out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+               break;
+       case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
+               /* CR 0 */
+               tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+               tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+               tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+               out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+               /* CR 1 */
+               tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+               tmp |= FSL_SRDSCR1_LANEE_OFF;
+               out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+               /* CR 2 */
+               tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+               tmp &= ~FSL_SRDSCR2_EICA_MASK;
+               tmp |= FSL_SRDSCR2_EICA_SGMII;
+               out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+               /* CR 3 */
+               tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+               tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+               tmp |= FSL_SRDSCR3_LANEA_SGMII;
+               out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+               break;
+       case 7: /* Lane A - disabled, Lane E - disabled */
+               /* CR 1 */
+               tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+               tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+               tmp |= FSL_SRDSCR1_LANEA_OFF;
+               tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+               tmp |= FSL_SRDSCR1_LANEE_OFF;
+               out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+               break;
+       default:
+               break;
+       }
+}
index 699441b..1cda1e3 100644 (file)
@@ -110,6 +110,10 @@ int get_clocks (void)
 #endif
        gd->i2c2_clk = gd->i2c1_clk;
 
+#if defined(CONFIG_MPC8536)
+       gd->sdhc_clk = gd->bus_clk / 2;
+#endif
+
 #if defined(CONFIG_CPM2)
        gd->vco_out = 2*sys_info.freqSystemBus;
        gd->cpm_clk = gd->vco_out / 2;
index e4e5c31..2e94614 100644 (file)
@@ -38,7 +38,7 @@ DECLARE_GLOBAL_DATA_PTR;
       defined(CONFIG_MPC8568) || \
       defined(CONFIG_MPC8641) || defined(CONFIG_MPC8610)
 #define FSL_HW_NUM_LAWS 10
-#elif defined(CONFIG_MPC8572)
+#elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572)
 #define FSL_HW_NUM_LAWS 12
 #else
 #error FSL_HW_NUM_LAWS not defined for this platform
index be2ce24..c09b07d 100644 (file)
@@ -70,9 +70,6 @@ typedef       struct  global_data {
 #if defined(CONFIG_MPC8315)
        u32 tdm_clk;
 #endif
-#if defined(CONFIG_MPC837X)
-       u32 sdhc_clk;
-#endif
        u32 core_clk;
        u32 enc_clk;
        u32 lbiu_clk;
@@ -89,6 +86,9 @@ typedef       struct  global_data {
        u32  mem_sec_clk;
 #endif /* CONFIG_MPC8360 */
 #endif
+#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC8536)
+       u32 sdhc_clk;
+#endif
 #if defined(CONFIG_MPC83XX) || defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
        u32 i2c1_clk;
        u32 i2c2_clk;
index 113ba48..559d6ea 100644 (file)
@@ -1560,6 +1560,7 @@ typedef struct ccsr_gur {
 #define MPC85xx_PORDEVSR_SGMII2_DIS    0x10000000
 #define MPC85xx_PORDEVSR_SGMII3_DIS    0x08000000
 #define MPC85xx_PORDEVSR_SGMII4_DIS    0x04000000
+#define MPC85xx_PORDEVSR_SRDS2_IO_SEL   0x38000000
 #define MPC85xx_PORDEVSR_IO_SEL                0x00380000
 #define MPC85xx_PORDEVSR_PCI2_ARB      0x00040000
 #define MPC85xx_PORDEVSR_PCI1_ARB      0x00020000
@@ -1653,13 +1654,23 @@ typedef struct ccsr_gur {
 #define CFG_MPC85xx_PCIX_ADDR  (CFG_IMMR + CFG_MPC85xx_PCIX_OFFSET)
 #define CFG_MPC85xx_PCIX2_OFFSET       (0x9000)
 #define CFG_MPC85xx_PCIX2_ADDR (CFG_IMMR + CFG_MPC85xx_PCIX2_OFFSET)
+#define CFG_MPC85xx_SATA1_OFFSET       (0x18000)
+#define CFG_MPC85xx_SATA1_ADDR (CFG_IMMR + CFG_MPC85xx_SATA1_OFFSET)
+#define CFG_MPC85xx_SATA2_OFFSET       (0x19000)
+#define CFG_MPC85xx_SATA2_ADDR (CFG_IMMR + CFG_MPC85xx_SATA2_OFFSET)
 #define CFG_MPC85xx_L2_OFFSET  (0x20000)
 #define CFG_MPC85xx_L2_ADDR    (CFG_IMMR + CFG_MPC85xx_L2_OFFSET)
 #define CFG_MPC85xx_DMA_OFFSET (0x21000)
 #define CFG_MPC85xx_DMA_ADDR   (CFG_IMMR + CFG_MPC85xx_DMA_OFFSET)
+#define CFG_MPC85xx_ESDHC_OFFSET       (0x2e000)
+#define CFG_MPC85xx_ESDHC_ADDR (CFG_IMMR + CFG_MPC85xx_ESDHC_OFFSET)
 #define CFG_MPC85xx_PIC_OFFSET (0x40000)
 #define CFG_MPC85xx_PIC_ADDR   (CFG_IMMR + CFG_MPC85xx_PIC_OFFSET)
 #define CFG_MPC85xx_CPM_OFFSET (0x80000)
 #define CFG_MPC85xx_CPM_ADDR   (CFG_IMMR + CFG_MPC85xx_CPM_OFFSET)
+#define CFG_MPC85xx_SERDES1_OFFSET     (0xE3000)
+#define CFG_MPC85xx_SERDES1_ADDR       (CFG_IMMR + CFG_MPC85xx_SERDES2_OFFSET)
+#define CFG_MPC85xx_SERDES2_OFFSET     (0xE3100)
+#define CFG_MPC85xx_SERDES2_ADDR       (CFG_IMMR + CFG_MPC85xx_SERDES2_OFFSET)
 
 #endif /*__IMMAP_85xx__*/
index dce4717..e07e5d3 100644 (file)
 
 #define SVR_8533       0x803400
 #define SVR_8533_E     0x803C00
+#define SVR_8536       0x803700
+#define SVR_8536_E     0x803F00
 #define SVR_8540       0x803000
 #define SVR_8541       0x807200
 #define SVR_8541_E     0x807A00
index 165456b..ae642b1 100644 (file)
 #define PCI_DEVICE_ID_MICROGATE_SCA    0x0030
 
 #define PCI_VENDOR_ID_FREESCALE                0x1957
+#define PCI_DEVICE_ID_MPC8536E         0x0050
+#define PCI_DEVICE_ID_MPC8536          0x0051
 #define PCI_DEVICE_ID_MPC8548E         0x0012
 #define PCI_DEVICE_ID_MPC8548          0x0013
 #define PCI_DEVICE_ID_MPC8543E         0x0014