• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef __HISOC_FLASH_H__
17 #define __HISOC_FLASH_H__
18 
19 #include "asm/platform.h"
20 #include "hisoc/sys_ctrl.h"
21 #include "asm/io.h"
22 #include "linux/delay.h"
23 #ifdef __cplusplus
24 #if __cplusplus
25 extern "C"{
26 #endif
27 #endif /* __cplusplus */
28 
29 /* FMC CRG register offset */
30 #define PERI_CRG48              0xc0
31 #define REG_FMC_CRG             PERI_CRG48
32 #define FMC_CLK_SEL(_clk)       (((_clk) & 0x7) << 2)
33 #define FMC_CLK_SEL_MASK        (0x7 << 2)
34 #define GET_CLK_TYPE(_reg)      (((_reg) >> 2) & 0x7)
35 /* SDR/DDR clock */
36 #define FMC_CLK_24M             0
37 #define FMC_CLK_75M             1
38 #define FMC_CLK_125M            2
39 #define FMC_CLK_150M            3
40 #define FMC_CLK_200M            4
41 #define FMC_CLK_250M            5
42 /* Only DDR clock */
43 #define FMC_CLK_300M            6
44 #define FMC_CLK_400M            7
45 #define FMC_CLK_ENABLE          (0x1 << 1)
46 #define FMC_SOFT_RST_REQ        (0x1 << 0)
47 
48 /* bit[9]=0: 3-Byte address mode; bit[9]=1: 4-Byte address mode */
49 #define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 9) & 0x1)
50 
51 /****************************************************************************/
52 /* REG_SYSSTAT 0: 3 Bytes address boot mode; 1: 4Bytes address boot mode */
53 #define REG_SYSSTAT            0x008C
54 #define GET_FMC_BOOT_MODE ({ \
55             unsigned int regval; \
56             unsigned int boot_mode = 0; \
57             regval = readl(SYS_CTRL_REG_BASE + REG_SYSSTAT); \
58             boot_mode = GET_SPI_NOR_ADDR_MODE(regval); \
59             boot_mode; })
60 
61 
62 /* This define just for Padctrl, PHY and DC configuration
63  * of nand flash */
64 #define MISC_CTRL28         0x28
65 #define EMMC_PHY_INIT_CTRL  IO_DEVICE_ADDR(0x12160004)
66 #define PHY_INIT_EN         0x1
67 #define PHY_ZCAL_EN         (0x1 << 3)
68 
69 #define EMMC_PHY_IOCTL_RONSEL_1_0   IO_DEVICE_ADDR(0x12160264)
70 #define RG_EMMC_RONSEL1             0x7ff
71 #define RG_EMMC_RONSEL0             0x7ff
72 #define EMMC_PHY_IOCTL_OD_RONSEL_2  IO_DEVICE_ADDR(0x12160268)
73 #define EMMC_PHY_IOCTL_IOE          IO_DEVICE_ADDR(0x1216026c)
74 #define NAND_IO_EN                  0x00ff00ff
75 
nand_io_config(void)76 static inline void nand_io_config(void)
77 {
78     /* Padctrl, PHY and DC configuration */
79     unsigned int reg_val = 0;
80     unsigned int timeout = 20;
81 
82     /* set pad ctrl reg for nand */
83     writel(0x1a3, IO_MUX_REG_BASE + 0x91c);
84     writel(0x103, IO_MUX_REG_BASE + 0x920);
85     writel(0x100, IO_MUX_REG_BASE + 0x924);
86     writel(0x1a3, IO_MUX_REG_BASE + 0x928);
87     writel(0x100, IO_MUX_REG_BASE + 0x92c);
88     writel(0x100, IO_MUX_REG_BASE + 0x930);
89 
90     /* disable emmc io isolation mode */
91     reg_val = readl(MISC_REG_BASE + MISC_CTRL28);
92     reg_val &= ~0x1;
93     writel(reg_val, MISC_REG_BASE + MISC_CTRL28);
94 
95     /* enable phy init */
96     reg_val = readl(EMMC_PHY_INIT_CTRL);
97     reg_val |= (PHY_INIT_EN | PHY_ZCAL_EN);
98     writel(reg_val, EMMC_PHY_INIT_CTRL);
99 
100     /* wait phy init and zcal done */
101     for(; ; ) {
102         reg_val = readl(EMMC_PHY_INIT_CTRL);
103         if (!(reg_val & (PHY_INIT_EN | PHY_ZCAL_EN)))
104             break;
105         udelay(100);
106         if (timeout-- == 0) {
107             dprintf("ERROR: wait mmc phy cal done time out\n");
108             return;
109         }
110     }
111 
112     /* DRV50 */
113     writel((RG_EMMC_RONSEL1 << 16) | RG_EMMC_RONSEL0,
114             EMMC_PHY_IOCTL_RONSEL_1_0);
115     /* DRV50, OD = 0 */
116     writel(0, EMMC_PHY_IOCTL_OD_RONSEL_2);
117 
118     writel(NAND_IO_EN, EMMC_PHY_IOCTL_IOE);
119 
120     writel(0x2, IO_MUX_REG_BASE + 69 * 4);
121     writel(0x2, IO_MUX_REG_BASE + 70 * 4);
122     writel(0x2, IO_MUX_REG_BASE + 71 * 4);
123     writel(0x2, IO_MUX_REG_BASE + 72 * 4);
124     writel(0x2, IO_MUX_REG_BASE + 73 * 4);
125     writel(0x2, IO_MUX_REG_BASE + 74 * 4);
126     writel(0x2, IO_MUX_REG_BASE + 75 * 4);
127     writel(0x2, IO_MUX_REG_BASE + 76 * 4);
128     writel(0x2, IO_MUX_REG_BASE + 79 * 4);
129     writel(0x2, IO_MUX_REG_BASE + 80 * 4);
130     writel(0x2, IO_MUX_REG_BASE + 81 * 4);
131     writel(0x2, IO_MUX_REG_BASE + 82 * 4);
132     writel(0x2, IO_MUX_REG_BASE + 83 * 4);
133     writel(0x2, IO_MUX_REG_BASE + 84 * 4);
134 }
135 
spi_io_config(void)136 static inline void spi_io_config(void)
137 {
138     /* set pad ctrl reg for spi */
139     writel(0x1C0, IO_MUX_REG_BASE + 0x91c);
140     writel(0x130, IO_MUX_REG_BASE + 0x920);
141     writel(0x130, IO_MUX_REG_BASE + 0x924);
142     writel(0x130, IO_MUX_REG_BASE + 0x928);
143     writel(0x130, IO_MUX_REG_BASE + 0x92c);
144     writel(0x103, IO_MUX_REG_BASE + 0x930);
145 
146     /* set mux ctrl reg for spi */
147     writel(0x1, IO_MUX_REG_BASE + 0x13c);
148     writel(0x1, IO_MUX_REG_BASE + 0x140);
149     writel(0x1, IO_MUX_REG_BASE + 0x144);
150     writel(0x1, IO_MUX_REG_BASE + 0x148);
151     writel(0x1, IO_MUX_REG_BASE + 0x14c);
152     writel(0x1, IO_MUX_REG_BASE + 0x150);
153 }
154 
155 /*---------------------------------------------------------------------------*/
156 /* hifmc100_set_fmc_system_clock */
157 /*---------------------------------------------------------------------------*/
hifmc100_set_system_clock(unsigned clock,int clk_en)158 static inline void hifmc100_set_system_clock(unsigned clock, int clk_en)
159 {
160     unsigned int old_val, regval;
161 
162     old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG);
163 
164     regval &= ~FMC_CLK_SEL_MASK;
165 
166     if (clock)
167         regval |= clock & FMC_CLK_SEL_MASK;
168     else {
169         regval |= FMC_CLK_SEL(FMC_CLK_24M); /* Default Clock */
170         spi_io_config();
171     }
172 
173     if (clk_en)
174         regval |= FMC_CLK_ENABLE;
175     else
176         regval &= ~FMC_CLK_ENABLE;
177 
178     if (regval != old_val)
179         writel(regval, (CRG_REG_BASE + REG_FMC_CRG));
180 }
181 
182 /*---------------------------------------------------------------------------*/
183 /* hifmc100_get_best_clock */
184 /*---------------------------------------------------------------------------*/
hifmc100_get_best_clock(unsigned int * clock)185 static inline void hifmc100_get_best_clock(unsigned int *clock)
186 {
187     int ix;
188     int clk_reg, clk_type;
189 
190 #define CLK_2X(_clk)    (((_clk) + 1) >> 1)
191     unsigned int sys_2X_clk[] = {
192         CLK_2X(24), FMC_CLK_SEL(FMC_CLK_24M),
193         CLK_2X(75), FMC_CLK_SEL(FMC_CLK_75M),
194         CLK_2X(125),    FMC_CLK_SEL(FMC_CLK_125M),
195         CLK_2X(150),    FMC_CLK_SEL(FMC_CLK_150M),
196         CLK_2X(200),    FMC_CLK_SEL(FMC_CLK_200M),
197         // CLK_2X(250),    FMC_CLK_SEL(FMC_CLK_250M),
198         0,      0,
199     };
200 #undef CLK_2X
201 
202     clk_type = FMC_CLK_24M;
203     clk_reg = FMC_CLK_SEL(clk_type);
204     for (ix = 0; sys_2X_clk[ix]; ix += 2) {
205         if (*clock < sys_2X_clk[ix])
206             break;
207         clk_reg = sys_2X_clk[ix + 1];
208         clk_type = GET_CLK_TYPE(clk_reg);
209     }
210 
211     *clock = clk_reg;
212 }
213 
hifmc100_nand_clk_enable(int enable)214 static inline void hifmc100_nand_clk_enable(int enable)
215 {
216     unsigned int old_val, regval;
217 
218     old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG);
219 
220     regval |= FMC_CLK_SEL(FMC_CLK_200M);
221 
222     if (enable)
223         regval |= FMC_CLK_ENABLE;
224     else
225         regval &= ~FMC_CLK_ENABLE;
226 
227     regval &= ~FMC_SOFT_RST_REQ;
228     if (regval != old_val)
229         writel(regval, (CRG_REG_BASE + REG_FMC_CRG));
230     nand_io_config();
231 }
232 
233 #ifdef __cplusplus
234 #if __cplusplus
235 }
236 #endif
237 #endif /* __cplusplus */
238 
239 #endif
240 
241