1 /*
2 * The Flash Memory Controller v100 Device Driver for hisilicon
3 *
4 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include <common.h>
22 #include <asm/io.h>
23 #include <asm/arch/platform.h>
24 #include <hifmc_common.h>
25
26 #include "hifmc_spi_ids.h"
27
28 #define REG_IO_BASE_FMC 0x10ff0000
29
30 /* configure io for SPI interface
31 * SPI NOR/SPI NAND 3V3 SDR
32 * Signal | Register | Value | Level
33 * CLK | 0x10FF0024 | 0x000002d1 | 3
34 * MOSI_IO0 | 0x10FF001C | 0x000000d1 | 3
35 * MISO_IO1 | 0x10FF0028 | 0x000000d1 | 3
36 * WP_IO2 | 0x10FF0020 | 0x000000d1 | 3
37 * HOLD_IO3 | 0x10FF002C | 0x000000d1 | 3
38 * SFC_CS0N | 0x10FF0030 | 0x00000031 | 1
39 * SFC_CS1N | 0x10FF0034 | 0x00000031 | 1
40 */
41 #define REG_SPI_CLK (REG_IO_BASE_FMC + 0x24)
42 #define REG_SPI_MOSI_IO0 (REG_IO_BASE_FMC + 0x1C)
43 #define REG_SPI_MISO_IO1 (REG_IO_BASE_FMC + 0x28)
44 #define REG_SPI_WP_IO2 (REG_IO_BASE_FMC + 0x20)
45 #define REG_SPI_HOLD_IO3 (REG_IO_BASE_FMC + 0x2c)
46 #define REG_SFC_CS0N (REG_IO_BASE_FMC + 0x30)
47 #define REG_SFC_CS1N (REG_IO_BASE_FMC + 0x34)
48
49 #define SPI_CLK_VAL 0x000002d1
50 #define SPI_MOSI_IO0_VAL 0x000000d1
51 #define SPI_MISO_IO1_VAL 0x000000d1
52 #define SPI_WP_IO2_VAL 0x000000d1
53 #define SPI_HOLD_IO3_VAL 0x000000d1
54 #define SPI_SFC_CS0N_VAL 0x00000031
55 #define SPI_SFC_CS1N_VAL 0x00000031
56
hi3531dv200_spi_io_config(void)57 static void hi3531dv200_spi_io_config(void)
58 {
59 static unsigned int io_config_flag = 1;
60
61 if (!io_config_flag)
62 return;
63
64 writel(SPI_CLK_VAL, REG_SPI_CLK);
65 writel(SPI_MOSI_IO0_VAL, REG_SPI_MOSI_IO0);
66 writel(SPI_MISO_IO1_VAL, REG_SPI_MISO_IO1);
67 writel(SPI_WP_IO2_VAL, REG_SPI_WP_IO2);
68 writel(SPI_HOLD_IO3_VAL, REG_SPI_HOLD_IO3);
69 writel(SPI_SFC_CS0N_VAL, REG_SFC_CS0N);
70 writel(SPI_SFC_CS1N_VAL, REG_SFC_CS1N);
71
72 io_config_flag = 0;
73 }
74
75 /*****************************************************************************/
hifmc_set_fmc_system_clock(struct spi_op * op,int clk_en)76 void hifmc_set_fmc_system_clock(struct spi_op *op, int clk_en)
77 {
78 unsigned int old_val, regval;
79
80 old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG);
81
82 regval &= ~FMC_CLK_SEL_MASK;
83
84 if (op && op->clock) {
85 regval |= op->clock & FMC_CLK_SEL_MASK;
86 fmc_pr(DTR_DB, "\t|||*-get the setting clock value: %#x\n",
87 op->clock);
88 } else {
89 regval |= fmc_clk_sel(FMC_CLK_24M); /* Default Clock */
90 hi3531dv200_spi_io_config();
91 }
92
93 if (clk_en)
94 regval |= FMC_CLK_ENABLE;
95 else
96 regval &= ~FMC_CLK_ENABLE;
97
98 if (regval != old_val) {
99 fmc_pr(DTR_DB, "\t|||*-setting system clock [%#x]%#x\n",
100 REG_FMC_CRG, regval);
101 writel(regval, (CRG_REG_BASE + REG_FMC_CRG));
102 }
103 }
104
105 /*****************************************************************************/
hifmc_get_fmc_best_2x_clock(unsigned int * clock)106 void hifmc_get_fmc_best_2x_clock(unsigned int *clock)
107 {
108 int ix;
109 unsigned int clk_reg, clk_type;
110 const char *str[] = {"12", "37.5", "62.5", "75", "100"};
111
112 #define CLK_2X(_clk) (((_clk) + 1) >> 1)
113 unsigned int sys_2X_clk[] = {
114 CLK_2X(24), fmc_clk_sel(FMC_CLK_24M),
115 CLK_2X(100), fmc_clk_sel(FMC_CLK_100M),
116 CLK_2X(150), fmc_clk_sel(FMC_CLK_150M),
117 CLK_2X(200), fmc_clk_sel(FMC_CLK_200M),
118 0, 0,
119 };
120 #undef CLK_2X
121
122 clk_type = FMC_CLK_24M;
123 clk_reg = fmc_clk_sel(clk_type);
124 fmc_pr(QE_DBG, "\t|||*-matching flash clock %d\n", *clock);
125 for (ix = 0; sys_2X_clk[ix]; ix += 2) {
126 if (*clock < sys_2X_clk[ix])
127 break;
128 clk_reg = sys_2X_clk[ix + 1];
129 clk_type = get_fmc_clk_type(clk_reg);
130 fmc_pr(QE_DBG, "\t||||-select system clock: %sMHz\n",
131 str[clk_type]);
132 }
133 #ifdef CONFIG_DTR_MODE_SUPPORT
134 fmc_pr(DTR_DB, "best system clock for SDR.\n");
135 #endif
136 fmc_pr(QE_DBG, "\t|||*-matched best system clock: %sMHz\n",
137 str[clk_type]);
138 *clock = clk_reg;
139 }
140
141 #ifdef CONFIG_DTR_MODE_SUPPORT
142 /*****************************************************************************/
hifmc_get_fmc_best_4x_clock(unsigned int * clock)143 void hifmc_get_fmc_best_4x_clock(unsigned int *clock)
144 {
145 int ix;
146 unsigned int clk_reg, clk_type;
147 char *const str[] = {"6", "9.25", "31.25", "37.5", "50",
148 "62.5", "75", "100"};
149
150 #define CLK_4X(_clk) (((_clk) + 1) >> 2)
151 unsigned int sys_4X_clk[] = {
152 CLK_4X(24), fmc_clk_sel(FMC_CLK_24M),
153 CLK_4X(100), fmc_clk_sel(FMC_CLK_100M),
154 CLK_4X(150), fmc_clk_sel(FMC_CLK_150M),
155 CLK_4X(200), fmc_clk_sel(FMC_CLK_200M),
156 CLK_4X(300), fmc_clk_sel(FMC_CLK_300M),
157 CLK_4X(400), fmc_clk_sel(FMC_CLK_400M),
158 0, 0,
159 };
160 #undef CLK_4X
161 clk_type = FMC_CLK_24M;
162 clk_reg = fmc_clk_sel(clk_type);
163 fmc_pr(DTR_DB, "\t|||*-matching flash clock %d\n", *clock);
164 for (ix = 0; sys_4X_clk[ix]; ix += 2) {
165 if (*clock < sys_4X_clk[ix])
166 break;
167 clk_reg = sys_4X_clk[ix + 1];
168 clk_type = get_fmc_clk_type(clk_reg);
169 fmc_pr(DTR_DB, "\t||||-select system clock: %sMHz\n",
170 str[clk_type]);
171 }
172 fmc_pr(DTR_DB, "best system clock for DTR.\n");
173 fmc_pr(DTR_DB, "\t|||*-matched best system clock: %sMHz\n",
174 str[clk_type]);
175 *clock = clk_reg;
176 }
177 /*****************************************************************************/
178 #endif/* CONFIG_DTR_MODE_SUPPORT */
179