8896b70e78dfc5672508c0c50ef7299f43979ac8
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / soc.c
1 /*
2  * Copyright 2014-2015 Freescale Semiconductor
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <fsl_ifc.h>
9 #include <asm/arch/soc.h>
10 #include <asm/io.h>
11 #include <asm/global_data.h>
12 #include <asm/arch-fsl-layerscape/config.h>
13
14 DECLARE_GLOBAL_DATA_PTR;
15
16 #if defined(CONFIG_LS2080A) || defined(CONFIG_LS2085A)
17 #ifdef CONFIG_SYS_FSL_ERRATUM_A009635
18 #define PLATFORM_CYCLE_ENV_VAR  "a009635_interval_val"
19
20 static unsigned long get_internval_val_mhz(void)
21 {
22         char *interval = getenv(PLATFORM_CYCLE_ENV_VAR);
23         /*
24          *  interval is the number of platform cycles(MHz) between
25          *  wake up events generated by EPU.
26          */
27         ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
28
29         if (interval)
30                 interval_mhz = simple_strtoul(interval, NULL, 10);
31
32         return interval_mhz;
33 }
34
35 void erratum_a009635(void)
36 {
37         u32 val;
38         unsigned long interval_mhz = get_internval_val_mhz();
39
40         if (!interval_mhz)
41                 return;
42
43         val = in_le32(DCSR_CGACRE5);
44         writel(val | 0x00000200, DCSR_CGACRE5);
45
46         val = in_le32(EPU_EPCMPR5);
47         writel(interval_mhz, EPU_EPCMPR5);
48         val = in_le32(EPU_EPCCR5);
49         writel(val | 0x82820000, EPU_EPCCR5);
50         val = in_le32(EPU_EPSMCR5);
51         writel(val | 0x002f0000, EPU_EPSMCR5);
52         val = in_le32(EPU_EPECR5);
53         writel(val | 0x20000000, EPU_EPECR5);
54         val = in_le32(EPU_EPGCR);
55         writel(val | 0x80000000, EPU_EPGCR);
56 }
57 #endif  /* CONFIG_SYS_FSL_ERRATUM_A009635 */
58
59 static void erratum_a008751(void)
60 {
61 #ifdef CONFIG_SYS_FSL_ERRATUM_A008751
62         u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
63
64         writel(0x27672b2a, scfg + SCFG_USB3PRM1CR / 4);
65 #endif
66 }
67
68 static void erratum_rcw_src(void)
69 {
70 #if defined(CONFIG_SPL)
71         u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
72         u32 __iomem *dcfg_dcsr = (u32 __iomem *)DCFG_DCSR_BASE;
73         u32 val;
74
75         val = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4);
76         val &= ~DCFG_PORSR1_RCW_SRC;
77         val |= DCFG_PORSR1_RCW_SRC_NOR;
78         out_le32(dcfg_dcsr + DCFG_DCSR_PORCR1 / 4, val);
79 #endif
80 }
81
82 #define I2C_DEBUG_REG 0x6
83 #define I2C_GLITCH_EN 0x8
84 /*
85  * This erratum requires setting glitch_en bit to enable
86  * digital glitch filter to improve clock stability.
87  */
88 static void erratum_a009203(void)
89 {
90         u8 __iomem *ptr;
91 #ifdef CONFIG_SYS_I2C
92 #ifdef I2C1_BASE_ADDR
93         ptr = (u8 __iomem *)(I2C1_BASE_ADDR + I2C_DEBUG_REG);
94
95         writeb(I2C_GLITCH_EN, ptr);
96 #endif
97 #ifdef I2C2_BASE_ADDR
98         ptr = (u8 __iomem *)(I2C2_BASE_ADDR + I2C_DEBUG_REG);
99
100         writeb(I2C_GLITCH_EN, ptr);
101 #endif
102 #ifdef I2C3_BASE_ADDR
103         ptr = (u8 __iomem *)(I2C3_BASE_ADDR + I2C_DEBUG_REG);
104
105         writeb(I2C_GLITCH_EN, ptr);
106 #endif
107 #ifdef I2C4_BASE_ADDR
108         ptr = (u8 __iomem *)(I2C4_BASE_ADDR + I2C_DEBUG_REG);
109
110         writeb(I2C_GLITCH_EN, ptr);
111 #endif
112 #endif
113 }
114
115 void fsl_lsch3_early_init_f(void)
116 {
117         erratum_a008751();
118         erratum_rcw_src();
119         init_early_memctl_regs();       /* tighten IFC timing */
120         erratum_a009203();
121 }
122
123 #elif defined(CONFIG_LS1043A)
124 void fsl_lsch2_early_init_f(void)
125 {
126         struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
127
128 #ifdef CONFIG_FSL_IFC
129         init_early_memctl_regs();       /* tighten IFC timing */
130 #endif
131
132         /*
133          * Enable snoop requests and DVM message requests for
134          * Slave insterface S4 (A53 core cluster)
135          */
136         out_le32(&cci->slave[4].snoop_ctrl,
137                  CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
138 }
139 #endif
140
141 #ifdef CONFIG_BOARD_LATE_INIT
142 int board_late_init(void)
143 {
144         return 0;
145 }
146 #endif