• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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