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_SPINOR_H__
17 #define __HISOC_SPINOR_H__
18
19 #include "asm/platform.h"
20 #include "asm/io.h"
21
22 #ifdef __cplusplus
23 #if __cplusplus
24 extern "C" {
25 #endif /* __cplusplus */
26 #endif /* __cplusplus */
27
28 #define PERI_CRG48 (CRG_REG_BASE + 0x00C0)
29 #define PERI_CRG48_RST (1 << 0)
30 #define PERI_CRG48_CLKEN (1 << 1)
31 #define PERI_CRG48_CLK_24M (0 << 2)
32 #define PERI_CRG48_CLK_75M ((0 << 3) | (1 << 2))
33 #define PERI_CRG48_CLK_125M ((1 << 2) | (1 << 3))
34
35 #define SFC_ADDR_MODE_REG (0x8C)
36 #define SFC_ADDR_MODE_MASK (0x80)
37 #define SFC_CLSEL_MASK (0xC)
38 #define SFC_PERI_CLKDIV1_SHIFT (28)
39 #define SFC_PERI_CLKDIV1_MASK (0xF)
40
41 /*****************************************************************************/
42 #undef GET_SFC_ADDR_MODE
43 #define GET_SFC_ADDR_MODE ({ \
44 int start_up_mode = 0; \
45 start_up_mode = readl(IO_ADDRESS(SYS_CTRL_REG_BASE + SFC_ADDR_MODE_REG)); \
46 start_up_mode &= SFC_ADDR_MODE_MASK; \
47 start_up_mode; })
48
49 /*****************************************************************************/
hisfc350_set_system_clock(unsigned clock,int clk_en)50 static inline void hisfc350_set_system_clock(unsigned clock, int clk_en)
51 {
52 unsigned int regval = readl(PERI_CRG48);
53
54 regval = regval & (~SFC_CLSEL_MASK);
55
56 if (clock) {
57 regval &= ~SFC_CLSEL_MASK;
58 regval |= clock & SFC_CLSEL_MASK;
59 } else {
60 regval &= ~SFC_CLSEL_MASK;
61 regval |= PERI_CRG48_CLK_24M; /* Default Clock */
62 }
63
64 if (clk_en)
65 regval |= PERI_CRG48_CLKEN;
66
67 if (regval != readl(PERI_CRG48))
68 writel(regval, (PERI_CRG48));
69 }
70
71 /*****************************************************************************/
hisfc350_get_best_clock(unsigned int * clock)72 static inline void hisfc350_get_best_clock(unsigned int *clock)
73 {
74 int ix;
75 int clk_reg;
76
77 #define CLK_2X(_clk) (((_clk) + 1) >> 1)
78 unsigned int sysclk[] = {
79 CLK_2X(24), PERI_CRG48_CLK_24M,
80 CLK_2X(75), PERI_CRG48_CLK_75M,
81 CLK_2X(125), PERI_CRG48_CLK_125M,
82 0, 0,
83 };
84 #undef CLK_2X
85
86 clk_reg = PERI_CRG48_CLK_24M;
87 for (ix = 0; sysclk[ix]; ix += 2) {
88 if (*clock < sysclk[ix])
89 break;
90 clk_reg = sysclk[ix + 1];
91 }
92
93 *clock = clk_reg;
94 }
95
96 /*****************************************************************************/
97 #ifdef CONFIG_HISFC350_SHOW_CYCLE_TIMING
hisfc350_get_clock_str(unsigned int clk_reg)98 static inline char * hisfc350_get_clock_str(unsigned int clk_reg)
99 {
100 static char buffer[40];
101
102 /* calculate reference PERI_CLKDIV1[31:28] */
103 SFC_PR(BT_DBG, "clk_reg=0x%0x.\n", clk_reg);
104 clk_reg = 216 / ((clk_reg >> SFC_PERI_CLKDIV1_SHIFT)
105 & SFC_PERI_CLKDIV1_MASK);
106 (VOID)sprintf_s(buffer, sizeof(buffer), "%dM", clk_reg);
107
108 return buffer;
109 }
110 #endif /* CONFIG_PERI_SHOW_CYCLE_TIMING */
111
112
113 #ifdef __cplusplus
114 #if __cplusplus
115 }
116 #endif /* __cplusplus */
117 #endif /* __cplusplus */
118
119
120 #endif
121
122