• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hifmc_hi3516dv300.c
3  *
4  * The Flash Memory Controller v100 Device Driver for hisilicon
5  *
6  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <common.h>
24 #include <asm/io.h>
25 #include <asm/arch/platform.h>
26 #include <hifmc_common.h>
27 
28 #include "hifmc_spi_ids.h"
29 
30 #define REG_IO_BASE 0x10ff0000
hi3516dv300_spi_io_config(void)31 static void hi3516dv300_spi_io_config(void)
32 {
33 	/* set pad ctrl reg for spi */
34 	writel(0x6a1, REG_IO_BASE + 0x0);   /* sfc_clk */
35 	writel(0x4e1, REG_IO_BASE + 0x4);   /* sfc_mosi_io3 */
36 	writel(0x4e1, REG_IO_BASE + 0x8);   /* sfc_wp_io2 */
37 	writel(0x4e1, REG_IO_BASE + 0xc);   /* sfc_miso_io1 */
38 	writel(0x5e1, REG_IO_BASE + 0x10);  /* sfc_csn */
39 	writel(0x4e1, REG_IO_BASE + 0x14);  /* sfc_hold_io0 */
40 }
41 
42 /*****************************************************************************/
hifmc_set_fmc_system_clock(struct spi_op * op,int clk_en)43 void hifmc_set_fmc_system_clock(struct spi_op *op, int clk_en)
44 {
45 	unsigned int old_val;
46 	unsigned int regval;
47 
48 	old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG);
49 
50 	regval &= ~FMC_CLK_SEL_MASK;
51 
52 	if (op && op->clock) {
53 		regval |= op->clock & FMC_CLK_SEL_MASK;
54 		fmc_pr(DTR_DB, "\t|||*-get the setting clock value: %#x\n",
55 			op->clock);
56 	} else {
57 		regval |= fmc_clk_sel(FMC_CLK_24M); /* Default Clock */
58 		hi3516dv300_spi_io_config();
59 	}
60 	if (clk_en)
61 		regval |= FMC_CLK_ENABLE;
62 	else
63 		regval &= ~FMC_CLK_ENABLE;
64 
65 	if (regval != old_val) {
66 		fmc_pr(DTR_DB, "\t|||*-setting system clock [%#x]%#x\n",
67 			REG_FMC_CRG, regval);
68 		writel(regval, (CRG_REG_BASE + REG_FMC_CRG));
69 	}
70 }
71 
72 /*****************************************************************************/
hifmc_get_fmc_best_2x_clock(unsigned int * clock)73 void hifmc_get_fmc_best_2x_clock(unsigned int *clock)
74 {
75 	int ix;
76 	unsigned int clk_reg;
77 	unsigned int clk_type;
78 	const char *str[] = {"12", "50", "75", "81.5", "100", "128.5"};
79 
80 	unsigned int sys_2x_clk[] = {
81 		clk_2x(24), fmc_clk_sel(FMC_CLK_24M),
82 		clk_2x(100), fmc_clk_sel(FMC_CLK_100M),
83 		clk_2x(150), fmc_clk_sel(FMC_CLK_150M),
84 		clk_2x(163), fmc_clk_sel(FMC_CLK_163M),
85 		clk_2x(200), fmc_clk_sel(FMC_CLK_200M),
86 		clk_2x(257), fmc_clk_sel(FMC_CLK_257M),
87 		0,      0,
88 	};
89 
90 	clk_type = FMC_CLK_24M;
91 	clk_reg = fmc_clk_sel(clk_type);
92 	fmc_pr(QE_DBG, "\t|||*-matching flash clock %d\n", *clock);
93 	for (ix = 0; sys_2x_clk[ix]; ix += _2B) {
94 		if (*clock < sys_2x_clk[ix])
95 			break;
96 		clk_reg = sys_2x_clk[ix + 1];
97 		clk_type = get_fmc_clk_type(clk_reg);
98 		fmc_pr(QE_DBG, "\t||||-select system clock: %sMHz\n",
99 			str[clk_type]);
100 	}
101 #ifdef CONFIG_DTR_MODE_SUPPORT
102 	fmc_pr(DTR_DB, "best system clock for SDR.\n");
103 #endif
104 	fmc_pr(QE_DBG, "\t|||*-matched best system clock: %sMHz\n",
105 		str[clk_type]);
106 	*clock = clk_reg;
107 }
108 
109 #ifdef CONFIG_DTR_MODE_SUPPORT
110 /*****************************************************************************/
hifmc_get_fmc_best_4x_clock(unsigned int * clock)111 void hifmc_get_fmc_best_4x_clock(unsigned int *clock)
112 {
113 	int ix;
114 	unsigned int clk_reg;
115 	unsigned int clk_type;
116 	char *const str[] = {"6", "25", "37.5", "40.75", "50", "64.25", "75", "99"};
117 
118 	unsigned int sys_4x_clk[] = {
119 		clk_4x(24), fmc_clk_sel(FMC_CLK_24M),
120 		clk_4x(100), fmc_clk_sel(FMC_CLK_100M),
121 		clk_4x(150), fmc_clk_sel(FMC_CLK_150M),
122 		clk_4x(163), fmc_clk_sel(FMC_CLK_163M),
123 		clk_4x(200), fmc_clk_sel(FMC_CLK_200M),
124 		clk_4x(257), fmc_clk_sel(FMC_CLK_257M),
125 		clk_4x(300), fmc_clk_sel(FMC_CLK_300M),
126 		clk_4x(396), fmc_clk_sel(FMC_CLK_396M),
127 		0,      0,
128 	};
129 
130 	clk_type = FMC_CLK_24M;
131 	clk_reg = fmc_clk_sel(clk_type);
132 	fmc_pr(DTR_DB, "\t|||*-matching flash clock %d\n", *clock);
133 	for (ix = 0; sys_4x_clk[ix]; ix += _2B) {
134 		if (*clock < sys_4x_clk[ix])
135 			break;
136 		clk_reg = sys_4x_clk[ix + 1];
137 		clk_type = get_fmc_clk_type(clk_reg);
138 		fmc_pr(DTR_DB, "\t||||-select system clock: %sMHz\n",
139 			str[clk_type]);
140 	}
141 	fmc_pr(DTR_DB, "best system clock for DTR.\n");
142 	fmc_pr(DTR_DB, "\t|||*-matched best system clock: %sMHz\n",
143 		str[clk_type]);
144 	*clock = clk_reg;
145 }
146 /*****************************************************************************/
147 #endif/* CONFIG_DTR_MODE_SUPPORT */
148