From: Sakar Arora Sakar.Arora@nxp.com
This patch adds the functions that initialize the following IPs on the SoC:
* Central Security Unit (CSU) - Acts as a gatekeeper for secure and non-secure accesses via SW. * TrustZone Address Space Controller (TZC-380). * Interconnect (CCI-400). * PLLs and Clocks. * ARM Generic Timer.
In addition it also provides functions that print the following useful information: * CPU Info * SoC Personality. * Board Personality. * Reset Configuration Word (RCW). * SerDes selection.
Signed-off-by: Bhupesh Sharma bhupesh.sharma@nxp.com --- .../Nxp/LS1043aRdb/Include/Library/Ls1043aSerDes.h | 89 +++ Platforms/Nxp/LS1043aRdb/Include/Library/SocLib.h | 203 ++++++- .../LS1043aRdb/Library/LS1043aRdbLib/LS1043aRdb.c | 2 + .../Library/LS1043aSocLib/LS1043aSocLib.c | 674 ++++++++++++++++++++- .../Library/LS1043aSocLib/LS1043aSocLib.inf | 13 + .../LS1043aRdb/Library/LS1043aSocLib/LsSerDes.c | 195 ++++++ 6 files changed, 1169 insertions(+), 7 deletions(-) create mode 100644 Platforms/Nxp/LS1043aRdb/Include/Library/Ls1043aSerDes.h create mode 100644 Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LsSerDes.c
diff --git a/Platforms/Nxp/LS1043aRdb/Include/Library/Ls1043aSerDes.h b/Platforms/Nxp/LS1043aRdb/Include/Library/Ls1043aSerDes.h new file mode 100644 index 0000000..181c268 --- /dev/null +++ b/Platforms/Nxp/LS1043aRdb/Include/Library/Ls1043aSerDes.h @@ -0,0 +1,89 @@ +/** Ls1043aSerDes.h + The Header file of SerDes Module + + Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __LS1043A_SERDES_H +#define __LS1043A_SERDES_H + +#define SRDS_MAX_LANES 4 + +#define LS1043_RCWSR4_SRDS1_PRTCL_MASK 0xFFFF0000 +#define LS1043_RCWSR4_SRDS1_PRTCL_SHIFT 16 + +typedef enum { + NONE = 0, + PCIE1, + PCIE2, + PCIE3, + SATA1, + XFI1, + XFI2, + SGMII1, + SGMII2, + SGMII3, + SGMII4, + SGMII5, + SGMII6, + SGMII7, + SGMII8, + SGMII9, + QSGMII1, + QSGMII2, + SERDES_PRCTL_COUNT +} SrdsPrtcl; + +enum Srds { + FSL_SRDS_1 = 0, + FSL_SRDS_2 = 1 +}; + +struct SerDesConfig { + UINT16 Protocol; + UINT8 SrdsLane[SRDS_MAX_LANES]; +}; + +struct SerDesConfig SerDes1ConfigTbl[] = { + /* SerDes 1 */ + {0x1555, {XFI1, PCIE1, PCIE2, PCIE3 } }, + {0x1560, {XFI1, PCIE1, PCIE3, PCIE3 } }, + {0x1460, {XFI1, QSGMII1, PCIE3, PCIE3 } }, + {0x1360, {XFI1, SGMII2, PCIE3, PCIE3 } }, + {0x2555, {SGMII9, PCIE1, PCIE2, PCIE3 } }, + {0x4555, {QSGMII1, PCIE1, PCIE2, PCIE3 } }, + {0x4558, {QSGMII1, PCIE1, PCIE2, SATA1 } }, + {0x1355, {XFI1, SGMII2, PCIE2, PCIE3 } }, + {0x1335, {XFI1, SGMII2, SGMII5, PCIE3 } }, + {0x1333, {XFI1, SGMII2, SGMII5, SGMII6 } }, + {0x2355, {SGMII9, SGMII2, PCIE2, PCIE3 } }, + {0x2260, {SGMII9, SGMII2, PCIE3, PCIE3 } }, + {0x2235, {SGMII9, SGMII2, SGMII5, PCIE3 } }, + {0x2233, {SGMII9, SGMII2, SGMII5, SGMII6 } }, + {0x3335, {SGMII9, SGMII2, SGMII5, PCIE3 } }, + {0x3355, {SGMII9, SGMII2, PCIE2, PCIE3 } }, + {0x3358, {SGMII9, SGMII2, PCIE2, SATA1 } }, + {0x3360, {SGMII9, SGMII2, PCIE3, PCIE3 } }, + {0x3560, {SGMII9, PCIE1, PCIE3, PCIE3 } }, + {0x3555, {SGMII9, PCIE1, PCIE2, PCIE3 } }, + {0x7000, {PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x9998, {PCIE1, PCIE2, PCIE3, SATA1 } }, + {0x6058, {PCIE1, PCIE1, PCIE2, SATA1 } }, + {0x1455, {XFI1, QSGMII1, PCIE2, PCIE3 } }, + {0x2455, {SGMII9, QSGMII1, PCIE2, PCIE3 } }, + {0x2255, {SGMII9, SGMII2, PCIE2, PCIE3 } }, + {0x3333, {SGMII9, SGMII2, SGMII5, SGMII6 } }, + {0x3338, {SGMII9, SGMII2, SGMII5, SATA1 } }, + {} +}; + +#endif /* __LS1043A_SERDES_H */ diff --git a/Platforms/Nxp/LS1043aRdb/Include/Library/SocLib.h b/Platforms/Nxp/LS1043aRdb/Include/Library/SocLib.h index d1655d5..dc798b3 100644 --- a/Platforms/Nxp/LS1043aRdb/Include/Library/SocLib.h +++ b/Platforms/Nxp/LS1043aRdb/Include/Library/SocLib.h @@ -22,14 +22,72 @@ #define HWA_CGA_M2_CLK_SEL 0x00000007 #define HWA_CGA_M2_CLK_SHIFT 0
+#define TP_ITYP_AV 0x00000001 /* Initiator available */ +#define TP_ITYP_TYPE(x) (((x) & 0x6) >> 1) /* Initiator Type */ +#define TP_ITYP_TYPE_ARM 0x0 +#define TP_ITYP_TYPE_PPC 0x1 /* PowerPC */ +#define TP_ITYP_TYPE_OTHER 0x2 /* StarCore DSP */ +#define TP_ITYP_TYPE_HA 0x3 /* HW Accelerator */ +#define TP_ITYP_THDS(x) (((x) & 0x18) >> 3) /* # threads */ +#define TP_ITYP_VER(x) (((x) & 0xe0) >> 5) /* Initiator Version */ +#define TY_ITYP_VER_A53 0x2 + +#define TP_CLUSTER_EOC_MASK 0xc0000000 /* end of clusters mask */ +#define TP_CLUSTER_INIT_MASK 0x0000003f /* initiator mask */ +#define TP_INIT_PER_CLUSTER 4 + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define LS1043A_CLK_FREQ 100000000 #define LS1043A_DDR_CLK_FREQ 100000000
#define LS1043A_MAX_CPUS 4 +#define LS1043A_FMAN_V3 #define LS1043A_NUM_FMAN 1 +#define LS1043A_NUM_FM1_DTSEC 7 +#define LS1043A_NUM_FM1_10GEC 1 + +/* + * Divide positive or negative dividend by positive divisor and round + * to closest UINTNeger. Result is undefined for negative divisors and + * for negative dividends if the divisor variable type is unsigned. + */ +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + (((typeof(x))-1) > 0 || \ + ((typeof(divisor))-1) > 0 || (__x) > 0) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ +} \ +) + +/* + * HammingWeight32: returns the hamming weight (i.e. the number + * of bits set) of a 32-bit word + */ +static inline UINTN HammingWeight32(UINTN w) +{ + UINTN Res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + Res = (Res & 0x33333333) + ((Res >> 2) & 0x33333333); + Res = (Res & 0x0F0F0F0F) + ((Res >> 4) & 0x0F0F0F0F); + Res = (Res & 0x00FF00FF) + ((Res >> 8) & 0x00FF00FF); + return (Res & 0x0000FFFF) + ((Res >> 16) & 0x0000FFFF); +} + +static inline UINTN CpuMaskNext(UINTN Cpu, UINTN Mask) +{ + for (Cpu++; !((1 << Cpu) & Mask); Cpu++) + ; + + return Cpu; +}
+#define ForEachCpu(iter, cpu, num_cpus, mask) \ + for (iter = 0, cpu = CpuMaskNext(-1, mask); \ + iter < num_cpus; \ + iter++, cpu = CpuMaskNext(cpu, mask)) \
struct SysInfo { UINTN FreqProcessor[LS1043A_MAX_CPUS]; @@ -41,9 +99,122 @@ struct SysInfo { UINTN FreqQman; };
+typedef struct SocClocks { + UINTN CpuClk; /* CPU clock in Hz! */ + UINTN BusClk; + UINTN MemClk; + UINTN PciClk; + UINTN SdhcClk; +} SocClockInfo; + +enum PeriphClock { + ARM_CLK = 0, + BUS_CLK, + UART_CLK, + ESDHC_CLK, + I2C_CLK, + DSPI_CLK, +}; + +enum CsuCslxAccess { + SEC_UNIT_NS_SUP_R = 0x08, + SEC_UNIT_NS_SUP_W = 0x80, + SEC_UNIT_NS_SUP_RW = 0x88, + SEC_UNIT_NS_USER_R = 0x04, + SEC_UNIT_NS_USER_W = 0x40, + SEC_UNIT_NS_USER_RW = 0x44, + SEC_UNIT_S_SUP_R = 0x02, + SEC_UNIT_S_SUP_W = 0x20, + SEC_UNIT_S_SUP_RW = 0x22, + SEC_UNIT_S_USER_R = 0x01, + SEC_UNIT_S_USER_W = 0x10, + SEC_UNIT_S_USER_RW = 0x11, + SEC_UNIT_ALL_RW = 0xff, +}; + +enum CsuCslxInd { + SEC_UNIT_CSLX_PCIE2_IO = 0, + SEC_UNIT_CSLX_PCIE1_IO, + SEC_UNIT_CSLX_MG2TPR_IP, + SEC_UNIT_CSLX_IFC_MEM, + SEC_UNIT_CSLX_OCRAM, + SEC_UNIT_CSLX_GIC, + SEC_UNIT_CSLX_PCIE1, + SEC_UNIT_CSLX_OCRAM2, + SEC_UNIT_CSLX_QSPI_MEM, + SEC_UNIT_CSLX_PCIE2, + SEC_UNIT_CSLX_SATA, + SEC_UNIT_CSLX_USB1, + SEC_UNIT_CSLX_QM_BM_SWPORTAL, + SEC_UNIT_CSLX_PCIE3 = 16, + SEC_UNIT_CSLX_PCIE3_IO, + SEC_UNIT_CSLX_USB3 = 20, + SEC_UNIT_CSLX_USB2, + SEC_UNIT_CSLX_SERDES = 32, + SEC_UNIT_CSLX_QDMA, + SEC_UNIT_CSLX_LPUART2, + SEC_UNIT_CSLX_LPUART1, + SEC_UNIT_CSLX_LPUART4, + SEC_UNIT_CSLX_LPUART3, + SEC_UNIT_CSLX_LPUART6, + SEC_UNIT_CSLX_LPUART5, + SEC_UNIT_CSLX_DSPI1 = 41, + SEC_UNIT_CSLX_QSPI, + SEC_UNIT_CSLX_ESDHC, + SEC_UNIT_CSLX_IFC = 45, + SEC_UNIT_CSLX_I2C1, + SEC_UNIT_CSLX_I2C3 = 48, + SEC_UNIT_CSLX_I2C2, + SEC_UNIT_CSLX_DUART2 = 50, + SEC_UNIT_CSLX_DUART1, + SEC_UNIT_CSLX_WDT2, + SEC_UNIT_CSLX_WDT1, + SEC_UNIT_CSLX_EDMA, + SEC_UNIT_CSLX_SYS_CNT, + SEC_UNIT_CSLX_DMA_MUX2, + SEC_UNIT_CSLX_DMA_MUX1, + SEC_UNIT_CSLX_DDR, + SEC_UNIT_CSLX_QUICC, + SEC_UNIT_CSLX_DCFG_CCU_RCPM = 60, + SEC_UNIT_CSLX_SECURE_BOOTROM, + SEC_UNIT_CSLX_SFP, + SEC_UNIT_CSLX_TMU, + SEC_UNIT_CSLX_SECURE_MONITOR, + SEC_UNIT_CSLX_SCFG, + SEC_UNIT_CSLX_FM = 66, + SEC_UNIT_CSLX_SEC5_5, + SEC_UNIT_CSLX_BM, + SEC_UNIT_CSLX_QM, + SEC_UNIT_CSLX_GPIO2 = 70, + SEC_UNIT_CSLX_GPIO1, + SEC_UNIT_CSLX_GPIO4, + SEC_UNIT_CSLX_GPIO3, + SEC_UNIT_CSLX_PLATFORM_CONT, + SEC_UNIT_CSLX_SEC_UNIT, + SEC_UNIT_CSLX_IIC4 = 77, + SEC_UNIT_CSLX_WDT4, + SEC_UNIT_CSLX_WDT3, + SEC_UNIT_CSLX_WDT5 = 81, + SEC_UNIT_CSLX_FTM2 = 86, + SEC_UNIT_CSLX_FTM1, + SEC_UNIT_CSLX_FTM4, + SEC_UNIT_CSLX_FTM3, + SEC_UNIT_CSLX_FTM6 = 90, + SEC_UNIT_CSLX_FTM5, + SEC_UNIT_CSLX_FTM8, + SEC_UNIT_CSLX_FTM7, + SEC_UNIT_CSLX_DSCR = 120, +}; + +struct CsuNsDev { + UINTN Ind; + UINT32 Val; +}; + /* Device Configuration and Pin Control */ struct CcsrGur { UINT32 porsr1; /* POR status 1 */ +#define FSL_CHASSIS2_CCSR_PORSR1_RCW_MASK 0xFF800000 UINT32 porsr2; /* POR status 2 */ UINT8 res_008[0x20-0x8]; UINT32 gpporcr1; /* General-purpose POR configuration */ @@ -51,6 +222,18 @@ struct CcsrGur { UINT32 dcfg_fusesr; /* Fuse status register */ UINT8 res_02c[0x70-0x2c]; UINT32 devdisr; /* Device disable control */ +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_1 0x80000000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_2 0x40000000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_3 0x20000000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_4 0x10000000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_5 0x08000000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_6 0x04000000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_9 0x00800000 +#define FSL_CHASSIS2_DEVDISR2_DTSEC1_10 0x00400000 +#define FSL_CHASSIS2_DEVDISR2_10GEC1_1 0x00800000 +#define FSL_CHASSIS2_DEVDISR2_10GEC1_2 0x00400000 +#define FSL_CHASSIS2_DEVDISR2_10GEC1_3 0x80000000 +#define FSL_CHASSIS2_DEVDISR2_10GEC1_4 0x40000000 UINT32 devdisr2; /* Device disable control 2 */ UINT32 devdisr3; /* Device disable control 3 */ UINT32 devdisr4; /* Device disable control 4 */ @@ -83,6 +266,8 @@ struct CcsrGur { #define FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK 0x1f #define FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT 16 #define FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK 0x3f +#define FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK 0xffff0000 +#define FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT 16 UINT8 res_140[0x200-0x140]; UINT32 scratchrw[4]; /* Scratch Read/Write */ UINT8 res_210[0x300-0x210]; @@ -259,6 +444,12 @@ struct CcsrClk { UINT8 res_c24[0x3dc]; };
+#define CCI400_CTRLORD_TERM_BARRIER 0x00000008 +#define CCI400_CTRLORD_EN_BARRIER 0 +#define CCI400_SHAORD_NON_SHAREABLE 0x00000002 +#define CCI400_DVM_MESSAGE_REQ_EN 0x00000002 +#define CCI400_SNOOP_REQ_EN 0x00000001 + /* CCI-400 registers */ struct CcsrCci400 { UINT32 ctrl_ord; /* Control Override */ @@ -301,8 +492,18 @@ struct CcsrCci400 { UINT8 res_e004[0x10000 - 0xe004]; };
+VOID EnableDevicesNsAccess(struct CsuNsDev *NonSecureDevices, UINT32 Num); + +VOID GetSysInfo(struct SysInfo *PtrSysInfo); + +VOID SocInit(VOID); + +VOID SerDesInit(VOID); + +VOID FdtCpuSetup(VOID *Blob); + UINT32 CalculateBaudDivisor(OUT UINT64 *BaudRate); -UINT32 CalculateI2cClockRate(VOID);
+UINT32 CalculateI2cClockRate(VOID);
#endif /* __LS1043A_SOC_H__ */ diff --git a/Platforms/Nxp/LS1043aRdb/Library/LS1043aRdbLib/LS1043aRdb.c b/Platforms/Nxp/LS1043aRdb/Library/LS1043aRdbLib/LS1043aRdb.c index 4fcb8a3..7c64709 100644 --- a/Platforms/Nxp/LS1043aRdb/Library/LS1043aRdbLib/LS1043aRdb.c +++ b/Platforms/Nxp/LS1043aRdb/Library/LS1043aRdbLib/LS1043aRdb.c @@ -24,6 +24,7 @@ #include <Library/PcdLib.h> #include <Ppi/ArmMpCoreInfo.h> #include <Library/PlatformLib.h> +#include <Library/SocLib.h>
/** Return the current Boot Mode @@ -47,6 +48,7 @@ ArmPlatformInitialize ( IN UINTN MpId ) { + SocInit(); return RETURN_SUCCESS; }
diff --git a/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.c b/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.c index fdeae08..2a7cb38 100644 --- a/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.c +++ b/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.c @@ -26,20 +26,227 @@ #include <Library/DebugAgentLib.h> #include <Library/IoLib.h> #include <Library/PrintLib.h> +#include <Library/SerialPortLib.h> +#include <Library/FslIfc.h>
+#include <Drivers/ArmTrustzone.h>
#include <Library/PlatformLib.h> #include <Library/SocLib.h> #include <Library/CpldLib.h>
+#include <libfdt.h> + +/* Global Clock Information pointer */ +static SocClockInfo gClkInfo; + +static struct CsuNsDev NonSecureDevices[] = +{ + {SEC_UNIT_CSLX_PCIE2_IO, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_PCIE1_IO, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_MG2TPR_IP, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_IFC_MEM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_OCRAM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_GIC, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_PCIE1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_OCRAM2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_QSPI_MEM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_PCIE2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SATA, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_USB1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_QM_BM_SWPORTAL, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_PCIE3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_PCIE3_IO, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_USB3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_USB2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SERDES, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_QDMA, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_LPUART2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_LPUART1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_LPUART4, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_LPUART3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_LPUART6, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_LPUART5, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DSPI1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_QSPI, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_ESDHC, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_IFC, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_I2C1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_I2C3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_I2C2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DUART2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DUART1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_WDT2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_WDT1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_EDMA, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SYS_CNT, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DMA_MUX2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DMA_MUX1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DDR, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_QUICC, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DCFG_CCU_RCPM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SECURE_BOOTROM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SFP, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_TMU, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SECURE_MONITOR, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SCFG, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SEC5_5, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_BM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_QM, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_GPIO2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_GPIO1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_GPIO4, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_GPIO3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_PLATFORM_CONT, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_SEC_UNIT, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_IIC4, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_WDT4, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_WDT3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_WDT5, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM2, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM1, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM4, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM3, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM6, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM5, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM8, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_FTM7, SEC_UNIT_ALL_RW}, + {SEC_UNIT_CSLX_DSCR, SEC_UNIT_ALL_RW}, +}; + +char *StringToMHz ( + char *Buf, + unsigned long Hz + ) +{ + long l, m, n; + + n = DIV_ROUND_CLOSEST(Hz, 1000) / 1000L; + l = AsciiSPrint (Buf, sizeof(Buf), "%ld", n); + + Hz -= n * 1000000L; + m = DIV_ROUND_CLOSEST(Hz, 1000L); + if (m != 0) + AsciiSPrint (Buf + l, sizeof(Buf), ".%03ld", m); + return (Buf); +} + +VOID +CciConfigureSnoopDvm ( + struct CcsrCci400 *CciBase + ) +{ + // Enable snoop requests and DVM message requests for + // Slave insterface S4 (A53 core cluster) + MmioWrite32((UINTN)&CciBase->slave[4].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); +} + +VOID IfcNorInit(VOID) { + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->cspr_cs[FSL_IFC_CS0].cspr_ext, FSL_IFC_NOR_CSPR_EXT); + + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->ftim_cs[FSL_IFC_CS0].ftim[FSL_IFC_FTIM0], FSL_IFC_NOR_FTIM0); + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->ftim_cs[FSL_IFC_CS0].ftim[FSL_IFC_FTIM1], FSL_IFC_NOR_FTIM1); + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->ftim_cs[FSL_IFC_CS0].ftim[FSL_IFC_FTIM2], FSL_IFC_NOR_FTIM2); + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->ftim_cs[FSL_IFC_CS0].ftim[FSL_IFC_FTIM3], FSL_IFC_NOR_FTIM3); + + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->cspr_cs[FSL_IFC_CS0].cspr, FSL_IFC_NOR_CSPR0); + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->amask_cs[FSL_IFC_CS0].amask, FSL_IFC_NOR_AMASK0); + MmioWriteBe32((UINTN) &(FSL_IFC_REGS_BASE)->csor_cs[FSL_IFC_CS0].csor, FSL_IFC_NOR_CSOR0); +} + +VOID +CciConfigureQos ( + struct CcsrCci400 *CciBase + ) +{ + // FIXME: Empty for now. Populate if required later. + return; +} + +VOID +Cci400Init ( + VOID + ) +{ + struct CcsrCci400 *Base = (struct CcsrCci400 *)LS1043A_CCI400_ADDR; + + /* Set CCI-400 control override register to enable barrier transaction */ + MmioWrite32((UINTN)&Base->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + + CciConfigureSnoopDvm(Base); + CciConfigureQos(Base); +} + +/** + Initialize the Secure peripherals and memory regions + + If Trustzone is supported by your platform then this function makes the required initialization + of the secure peripherals and memory regions. + +**/ +VOID +Tzc380Init ( + VOID + ) +{ + // Setup TZ Address Space Controller. + // Assumption: We have 2GB DDR mounted on the DIMMs. + // + // Since, we need ONE secure DDR region which will be used for keeping + // the PPA (EL3 platform security fw) code and the rest of the regions + // would be non-secure regions which can be accessed via NS software as + // well - so we create one TZASC region of 2GB and divided it into + // 8 equal su-regions. Now, we keep the 1st sub-regions for housing + // the PPA and use the rest of the sub-regions to allow NS accesses. + + // Note: Your OS Kernel must be aware of the secure regions before to + // enable this region + TZASCSetRegion(LS1043A_TZASC380_ADDR, 1, TZASC_REGION_ENABLED, LS1043A_DRAM1_BASE_ADDR, 0, + TZASC_REGION_SIZE_2GB, TZASC_REGION_SECURITY_SRW, 0x7F); +} + +VOID +EnableDevicesNsAccess ( + OUT struct CsuNsDev *NonSecureDevices, + IN UINT32 Num + ) +{ + UINT32 *Base = (UINT32 *)LS1043A_CSU_ADDR; + UINT32 *Reg; + UINT32 Val; + UINT32 Count; + + for (Count = 0; Count < Num; Count++) { + Reg = Base + NonSecureDevices[Count].Ind / 2; + Val = MmioReadBe32((UINTN)Reg); + if (NonSecureDevices[Count].Ind % 2 == 0) { + Val &= 0x0000ffff; + Val |= NonSecureDevices[Count].Val << 16; + } else { + Val &= 0xffff0000; + Val |= NonSecureDevices[Count].Val; + } + MmioWriteBe32((UINTN)Reg, Val); + } +} + +VOID +CsuInit ( + VOID + ) +{ + EnableDevicesNsAccess(NonSecureDevices, ARRAY_SIZE(NonSecureDevices)); +}
VOID GetSysInfo ( OUT struct SysInfo *PtrSysInfo ) { - struct CcsrGur *GurBase = (void *)(LS1043A_FSL_GUTS_ADDR); - struct CcsrClk *ClkBase = (void *)(LS1043A_FSL_CLK_ADDR); + struct CcsrGur *GurBase = (void *)(LS1043A_GUTS_ADDR); + struct CcsrClk *ClkBase = (void *)(LS1043A_CLK_ADDR); UINTN CpuIndex; UINT32 TempRcw; const UINT8 CoreCplxPll[8] = { @@ -57,8 +264,8 @@ GetSysInfo ( };
UINTN PllCount; - UINTN FreqCPll[LS1043A_FSL_NUM_CC_PLLS]; - UINTN PllRatio[LS1043A_FSL_NUM_CC_PLLS]; + UINTN FreqCPll[LS1043A_NUM_CC_PLLS]; + UINTN PllRatio[LS1043A_NUM_CC_PLLS]; UINTN SysClk = LS1043A_CLK_FREQ;
PtrSysInfo->FreqSystemBus = SysClk; @@ -71,7 +278,7 @@ GetSysInfo ( FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) & FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
- for (PllCount = 0; PllCount < LS1043A_FSL_NUM_CC_PLLS; PllCount++) { + for (PllCount = 0; PllCount < LS1043A_NUM_CC_PLLS; PllCount++) { PllRatio[PllCount] = (MmioReadBe32((UINTN)&ClkBase->pllcgsr[PllCount].pllcngsr) >> 1) & 0xff; if (PllRatio[PllCount] > 4) FreqCPll[PllCount] = SysClk * PllRatio[PllCount]; @@ -112,6 +319,461 @@ GetSysInfo ( PtrSysInfo->FreqQman = PtrSysInfo->FreqSystemBus / 2; }
+VOID +ClockInit ( + VOID + ) +{ + struct SysInfo SocSysInfo; + + GetSysInfo(&SocSysInfo); + gClkInfo.CpuClk = SocSysInfo.FreqProcessor[0]; + gClkInfo.BusClk = SocSysInfo.FreqSystemBus; + gClkInfo.MemClk = SocSysInfo.FreqDdrBus; + gClkInfo.SdhcClk = SocSysInfo.FreqSdhc; +} + +INTN +TimerInit ( + VOID + ) +{ + UINT32 *TimerBase = (UINT32 *)LS1043A_TIMER_ADDR; + + if (PcdGetBool(PcdCounterFrequencyReal)) { + UINTN cntfrq = PcdGet32(PcdCounterFrequency); + + /* Update with accurate clock frequency */ + asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); + } + + /* Enable clock for timer. This is a global setting. */ + MmioWrite32((UINTN)TimerBase, 0x1); + + return 0; +} + +static inline +UINT32 +InitiatorType ( + IN UINT32 Cluster, + IN UINTN InitId + ) +{ + struct CcsrGur *GurBase = (void *)(LS1043A_GUTS_ADDR); + UINT32 Idx = (Cluster >> (InitId * 8)) & TP_CLUSTER_INIT_MASK; + UINT32 Type = MmioReadBe32((UINTN)&GurBase->tp_ityp[Idx]); + + if (Type & TP_ITYP_AV) + return Type; + + return 0; +} + +UINT32 +CpuMask ( + VOID + ) +{ + struct CcsrGur *GurBase = (void *)(LS1043A_GUTS_ADDR); + UINTN ClusterIndex = 0, Count = 0; + UINT32 Cluster, Type, Mask = 0; + + do { + UINTN InitiatorIndex; + Cluster = MmioReadBe32((UINTN)&GurBase->tp_cluster[ClusterIndex].lower); + for (InitiatorIndex = 0; InitiatorIndex < TP_INIT_PER_CLUSTER; InitiatorIndex++) { + Type = InitiatorType(Cluster, InitiatorIndex); + if (Type) { + if (TP_ITYP_TYPE(Type) == TP_ITYP_TYPE_ARM) + Mask |= 1 << Count; + Count++; + } + } + ClusterIndex++; + } while ((Cluster & TP_CLUSTER_EOC_MASK) == 0x0); + + return Mask; +} + +/* + * Return the number of cores on this SOC. + */ +UINTN +CpuNumCores ( + VOID + ) +{ + return HammingWeight32(CpuMask()); +} + +UINT32 +QoriqCoreToType ( + IN UINTN Core + ) +{ + struct CcsrGur *GurBase = (VOID *)(LS1043A_GUTS_ADDR); + UINTN ClusterIndex = 0, Count = 0; + UINT32 Cluster, Type; + + do { + UINTN InitiatorIndex; + Cluster = MmioReadBe32((UINTN)&GurBase->tp_cluster[ClusterIndex].lower); + for (InitiatorIndex = 0; InitiatorIndex < TP_INIT_PER_CLUSTER; InitiatorIndex++) { + Type = InitiatorType(Cluster, InitiatorIndex); + if (Type) { + if (Count == Core) + return Type; + Count++; + } + } + ClusterIndex++; + } while ((Cluster & TP_CLUSTER_EOC_MASK) == 0x0); + + return -1; /* cannot identify the cluster */ +} + +VOID +PrintCpuInfo ( + VOID + ) +{ + struct SysInfo SysInfo; + UINTN CoreIndex, Core; + UINT32 Type; + CHAR8 Buf[32]; + CHAR8 Buffer[100]; + UINTN CharCount; + + GetSysInfo(&SysInfo); + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Clock Configuration:"); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + ForEachCpu(CoreIndex, Core, CpuNumCores(), CpuMask()) { + if (!(CoreIndex % 3)) + DEBUG((EFI_D_INFO, "\n ")); + Type = TP_ITYP_VER(QoriqCoreToType(Core)); + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "CPU%d(%a):%-4a MHz ", Core, + Type == TY_ITYP_VER_A53 ? "A53" : "Unknown Core", + StringToMHz(Buf, SysInfo.FreqProcessor[Core])); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + } + + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "\n Bus: %-4a MHz ", + StringToMHz(Buf, SysInfo.FreqSystemBus)); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "DDR: %-4a MHz", StringToMHz(Buf, SysInfo.FreqDdrBus)); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "\n"); + SerialPortWrite ((UINT8 *) Buffer, CharCount); +} + +VOID +PrintSocPersonality ( + VOID + ) +{ +} + +VOID +IfcInit ( + VOID + ) +{ + /* NOR Init */ + IfcNorInit(); + + /* CPLD Init */ + CpldInit(); +} + +VOID +PrintBoardPersonality ( + VOID + ) +{ + static const char *Freq[3] = {"100.00MHZ", "156.25MHZ"}; + UINT8 RcwSrc1, RcwSrc2; + UINT32 RcwSrc; + UINT32 sd1refclk_sel; + + DEBUG((EFI_D_INFO, "Board: LS1043ARDB, boot from ")); + + RcwSrc1 = CPLD_READ(RcwSource1); + RcwSrc2 = CPLD_READ(RcwSource1); + CpldRevBit(&RcwSrc1); + RcwSrc = RcwSrc1; + RcwSrc = (RcwSrc << 1) | RcwSrc2; + + if (RcwSrc == 0x25) + DEBUG((EFI_D_INFO, "vBank %d\n", CPLD_READ(Vbank))); + else if (RcwSrc == 0x106) + DEBUG((EFI_D_INFO, "NAND\n")); + else + DEBUG((EFI_D_INFO, "Invalid setting of SW4\n")); + + DEBUG((EFI_D_INFO, "CPLD: V%x.%x\nPCBA: V%x.0\n", CPLD_READ(CpldVersionMajor), + CPLD_READ(CpldVersionMinor), CPLD_READ(PcbaVersion))); + + DEBUG((EFI_D_INFO, "SERDES Reference Clocks:\n")); + sd1refclk_sel = CPLD_READ(Sd1RefClkSel); + DEBUG((EFI_D_INFO, "SD1_CLK1 = %a, SD1_CLK2 = %a\n", Freq[sd1refclk_sel], Freq[0])); +} + +VOID +PrintRCW ( + VOID + ) +{ + struct CcsrGur *Base = (void *)(LS1043A_GUTS_ADDR); + UINTN Count; + CHAR8 Buffer[100]; + UINTN CharCount; + + /* + * Display the RCW, so that no one gets confused as to what RCW + * we're actually using for this boot. + */ + + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), + "Reset Configuration Word (RCW):"); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + for (Count = 0; Count < ARRAY_SIZE(Base->rcwsr); Count++) { + UINT32 Rcw = MmioReadBe32((UINTN)&Base->rcwsr[Count]); + + if ((Count % 4) == 0) { + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), + "\n %08x:", Count * 4); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + } + + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), " %08x", Rcw); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + } + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "\n"); + SerialPortWrite ((UINT8 *) Buffer, CharCount); +} + +VOID +SmmuInit ( + VOID + ) +{ + UINT32 Value; + + /* set pagesize as 64K and ssmu-500 in bypass mode */ + Value = (MmioRead32((UINTN)SMMU_REG_SACR) | SACR_PAGESIZE_MASK); + MmioWrite32((UINTN)SMMU_REG_SACR, Value); + + Value = (MmioRead32((UINTN)SMMU_REG_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); + MmioWrite32((UINTN)SMMU_REG_SCR0, Value); + + Value = (MmioRead32((UINTN)SMMU_REG_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); + MmioWrite32((UINTN)SMMU_REG_NSCR0, Value); +} + +/** + Function to initialize SoC specific constructs + // CSU + // TZC-380 + // CCI-400 + // ClockInit + // TimerInit + // CPU Info + // SoC Personality + // Board Personality + // RCW prints + // SerDes support + **/ +VOID +SocInit ( + VOID + ) +{ + + CHAR8 Buffer[100]; + UINTN CharCount; + + // LS1043A SoC has a CSU (Central Security Unit) + if (PcdGetBool(PcdCsuInitialize)) + CsuInit(); + + if (PcdGetBool(PcdTzc380Initialize)) + Tzc380Init(); + + if (PcdGetBool(PcdCci400Initialize)) + Cci400Init(); + + if (PcdGetBool(PcdClockInitialize)) + ClockInit(); + + SmmuInit(); + TimerInit(); + + // Initialize the Serial Port + SerialPortInitialize (); + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "\nUEFI firmware (version %s built at %a on %a)\n\r", + (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + PrintCpuInfo(); + PrintRCW(); + + PrintSocPersonality(); + + IfcInit(); + + PrintBoardPersonality(); + + SerDesInit(); + return; +} + +/* fdt fixup for LS1043A */ + +VOID +FixupByCompatibleField ( + VOID *Fdt, + CONST char *Compat, + CONST char *Prop, + CONST VOID *Val, + INTN Len, + INTN Create + ) +{ + INTN Offset = -1; + Offset = fdt_node_offset_by_compatible(Fdt, -1, Compat); + while (Offset != -FDT_ERR_NOTFOUND) { + if (Create || (fdt_get_property(Fdt, Offset, Prop, NULL) != NULL)) + fdt_setprop(Fdt, Offset, Prop, Val, Len); + Offset = fdt_node_offset_by_compatible(Fdt, Offset, Compat); + } +} + +VOID +FixupByCompatibleField32 ( + VOID *Fdt, + CONST char *Compat, + CONST char *Prop, + UINT32 Val, + INTN Create + ) +{ + fdt32_t Tmp = cpu_to_fdt32(Val); + FixupByCompatibleField(Fdt, Compat, Prop, &Tmp, 4, Create); +} + +#define BMAN_IP_REV_1 0xBF8 +#define BMAN_IP_REV_2 0xBFC +VOID +FdtFixupBmanPortals ( + VOID *Blob + ) +{ + UINTN Off, Err; + UINTN Maj, Min; + UINTN IpCfg; + + UINT32 BmanRev1 = MmioReadBe32(LS1043A_BMAN_ADDR + BMAN_IP_REV_1); + UINT32 BmanRev2 = MmioReadBe32(LS1043A_BMAN_ADDR + BMAN_IP_REV_2); + char Compatible[64]; + INTN CompatibleLength; + + Maj = (BmanRev1 >> 8) & 0xff; + Min = BmanRev1 & 0xff; + + IpCfg = BmanRev2 & 0xff; + + CompatibleLength = AsciiSPrint(Compatible, sizeof(Compatible), + "fsl,bman-portal-%u.%u.%u", + Maj, Min, IpCfg) + 1; + CompatibleLength += AsciiSPrint(Compatible + CompatibleLength, + sizeof(Compatible), "fsl,bman-portal") + + 1; + + Off = fdt_node_offset_by_compatible(Blob, -1, "fsl,bman-portal"); + while (Off != -FDT_ERR_NOTFOUND) { + Err = fdt_setprop(Blob, Off, "compatible", Compatible, + CompatibleLength); + if (Err < 0) { + DEBUG((EFI_D_ERROR, "ERROR: unable to create props for %a: %s\n", + fdt_get_name(Blob, Off, NULL), fdt_strerror(Err))); + return; + } + + Off = fdt_node_offset_by_compatible(Blob, Off, "fsl,bman-portal"); + } +} + +#define QMAN_IP_REV_1 0xBF8 +#define QMAN_IP_REV_2 0xBFC +VOID +FdtFixupQmanPortals ( + VOID *Blob + ) +{ + INTN Off, Err; + UINTN Maj, Min; + UINTN IpCfg; + UINT32 QmanRev1 = MmioReadBe32(LS1043A_QMAN_ADDR + QMAN_IP_REV_1); + UINT32 QmanRev2 = MmioReadBe32(LS1043A_QMAN_ADDR + QMAN_IP_REV_2); + char Compatible[64]; + INTN CompatLength; + + Maj = (QmanRev1 >> 8) & 0xff; + Min = QmanRev1 & 0xff; + IpCfg = QmanRev2 & 0xff; + + CompatLength = AsciiSPrint(Compatible, sizeof(Compatible), + "fsl,qman-portal-%u.%u.%u", + Maj, Min, IpCfg) + 1; + CompatLength += AsciiSPrint(Compatible + CompatLength, + sizeof(Compatible), "fsl,qman-portal") + 1; + + Off = fdt_node_offset_by_compatible(Blob, -1, "fsl,qman-portal"); + while (Off != -FDT_ERR_NOTFOUND) { + Err = fdt_setprop(Blob, Off, "compatible", Compatible, + CompatLength); + if (Err < 0) { + DEBUG((EFI_D_ERROR, "ERROR: unable to create props for %a: %a\n", + fdt_get_name(Blob, Off, NULL), fdt_strerror(Err))); + return; + } + + Off = fdt_node_offset_by_compatible(Blob, Off, "fsl,qman-portal"); + } +} + +VOID +FdtFixupSdhc ( + VOID *Blob, + UINTN SdhcClk + ) +{ + const char *Compatible = "fsl,esdhc"; + + FixupByCompatibleField32(Blob, Compatible, "clock-frequency", SdhcClk, 1); + + FixupByCompatibleField(Blob, Compatible, "status", "okay", 4 + 1, 1); +} + +VOID FdtCpuSetup(VOID *blob) +{ + struct SysInfo SocSysInfo; + GetSysInfo(&SocSysInfo); + + FixupByCompatibleField32(blob, "fsl,ns16550", + "clock-frequency", SocSysInfo.FreqSystemBus, 1); + + FdtFixupSdhc(blob, SocSysInfo.FreqSdhc); + + FdtFixupBmanPortals(blob); + FdtFixupQmanPortals(blob); + + FixupByCompatibleField32(blob, "fsl,qman", + "clock-frequency", SocSysInfo.FreqQman, 1); +} +
UINT32 CalculateBaudDivisor ( @@ -135,6 +797,6 @@ CalculateI2cClockRate( struct SysInfo SocSysInfo;
GetSysInfo(&SocSysInfo); - return SocSysInfo.FreqSystemBus;
+ return SocSysInfo.FreqSystemBus; } diff --git a/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.inf b/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.inf index 322fe34..307cf21 100644 --- a/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.inf +++ b/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LS1043aSocLib.inf @@ -29,12 +29,25 @@ OpenPlatformPkg/Chips/Nxp/QoriqLs/NxpQoriqLs.dec
[LibraryClasses] + ArmTrustZoneLib BaseLib CpldLib DebugLib DebugAgentLib IoLib ArmLib + MemoryAllocationLib + SerialPortLib
[Sources.common] LS1043aSocLib.c + LsSerDes.c + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString + gArmPlatformTokenSpaceGuid.PcdCounterFrequencyReal + gArmPlatformTokenSpaceGuid.PcdCsuInitialize + gArmPlatformTokenSpaceGuid.PcdTzc380Initialize + gArmPlatformTokenSpaceGuid.PcdCci400Initialize + gArmPlatformTokenSpaceGuid.PcdClockInitialize + gArmPlatformTokenSpaceGuid.PcdCounterFrequency diff --git a/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LsSerDes.c b/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LsSerDes.c new file mode 100644 index 0000000..3312e9b --- /dev/null +++ b/Platforms/Nxp/LS1043aRdb/Library/LS1043aSocLib/LsSerDes.c @@ -0,0 +1,195 @@ +/** LsSerDes.c + Provides the basic interfaces for SerDes Module + + Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <Uefi.h> +#include <Library/PlatformLib.h> +#include <Library/SocLib.h> +#include <Library/DebugLib.h> +#include <Library/DebugAgentLib.h> +#include <Library/IoLib.h> +#include <Library/Ls1043aSerDes.h> + +#ifdef LS1043A_SRDS_1 +static UINT16 SerDes1PrtclMap[SERDES_PRCTL_COUNT]; +#endif + +static struct SerDesConfig *SerDesConfigTbl[] = { + SerDes1ConfigTbl +}; + +SrdsPrtcl +GetSerDesPrtcl +( + IN INTN SerDes, + IN INTN Cfg, + IN INTN Lane +) +{ + struct SerDesConfig *Config; + + if (SerDes >= ARRAY_SIZE(SerDesConfigTbl)) + return 0; + + Config = SerDesConfigTbl[SerDes]; + while (Config->Protocol) { + if (Config->Protocol == Cfg) { + return Config->SrdsLane[Lane]; + } + Config++; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CheckSerDesPrtclValid +( + IN INTN SerDes, + IN UINT32 Prtcl +) +{ + INTN Cnt; + struct SerDesConfig *Config; + + if (SerDes >= ARRAY_SIZE(SerDesConfigTbl)) + return 0; + + Config = SerDesConfigTbl[SerDes]; + while (Config->Protocol) { + if (Config->Protocol == Prtcl) { + DEBUG((EFI_D_INFO, "Protocol: %x Matched with the one in Table\n", Prtcl)); + break; + } + Config++; + } + + if (!Config->Protocol) + return 0; + + for (Cnt = 0; Cnt < SRDS_MAX_LANES; Cnt++) { + if (Config->SrdsLane[Cnt] != NONE) + return 1; + } + + return 0; +} + + +EFI_STATUS +IsSerDesConfigured +( + IN SrdsPrtcl Device +) +{ + INTN Ret = 0; + +#ifdef LS1043A_SRDS_1 + Ret |= SerDes1PrtclMap[Device]; +#endif + + return !!Ret; +} + +INTN +GetSerDesFirstLane +( + IN UINT32 Sd, + IN SrdsPrtcl Device +) +{ + struct CcsrGur *Gur = (void *)(LS1043A_GUTS_ADDR); + UINT32 Cfg = MmioReadBe32((UINTN)&Gur->rcwsr[4]); + INTN Cnt; + + switch (Sd) { +#ifdef LS1043A_SRDS_1 + case FSL_SRDS_1: + Cfg &= LS1043_RCWSR4_SRDS1_PRTCL_MASK; + Cfg >>= LS1043_RCWSR4_SRDS1_PRTCL_SHIFT; + break; +#endif + default: + DEBUG((EFI_D_INFO, "Invalid SerDes%d, Only one SerDes is there.\n", Sd)); + break; + } + + /* Is serdes enabled at all? */ + if (Cfg == 0) + return EFI_DEVICE_ERROR; + + for (Cnt = 0; Cnt < SRDS_MAX_LANES; Cnt++) { + if (GetSerDesPrtcl(Sd, Cfg, Cnt) == Device) + return Cnt; + } + + return EFI_DEVICE_ERROR; +} + +VOID +LSSerDesInit +( + UINT32 Srds, + UINT32 SrdsAddr, + UINT32 SrdsPrtclMask, + UINT32 SrdsPrtclShift, + UINT16 SerDesPrtclMap[SERDES_PRCTL_COUNT] +) +{ + struct CcsrGur *Gur = (VOID *)(LS1043A_GUTS_ADDR); + UINT32 SrdsProt; + INTN Lane; + UINT32 Flag = 0; + + SrdsProt = MmioReadBe32((UINTN)&Gur->rcwsr[4]) & SrdsPrtclMask; + SrdsProt >>= SrdsPrtclShift; + + DEBUG((EFI_D_INFO, "Using SERDES%d Protocol: %d (0x%x)\n", Srds + 1, SrdsProt, SrdsProt)); + + if (!CheckSerDesPrtclValid(Srds, SrdsProt)) { + DEBUG((EFI_D_ERROR, "SERDES%d[PRTCL] = 0x%x is not valid\n", Srds + 1, SrdsProt)); + Flag++; + } + + for (Lane = 0; Lane < SRDS_MAX_LANES; Lane++) { + SrdsPrtcl LanePrtcl = GetSerDesPrtcl(Srds, SrdsProt, Lane); + if (LanePrtcl >= SERDES_PRCTL_COUNT) { + DEBUG((EFI_D_ERROR, "Unknown SerDes lane protocol %d\n", LanePrtcl)); + Flag++; + } else { + SerDesPrtclMap[LanePrtcl] = 1; + } + } + + if (Flag) + DEBUG((EFI_D_ERROR, "Could not configure SerDes module!!\n")); + else + DEBUG((EFI_D_INFO, "Successfully configured SerDes module!!\n")); +} + +VOID +SerDesInit +( + VOID +) +{ + DEBUG((EFI_D_INFO, "Initializing SerDes....\n")); +#ifdef LS1043A_SRDS_1 + LSSerDesInit(FSL_SRDS_1, + LS1043A_SERDES_ADDR, + LS1043_RCWSR4_SRDS1_PRTCL_MASK, + LS1043_RCWSR4_SRDS1_PRTCL_SHIFT, + SerDes1PrtclMap); +#endif +}