• 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 HP_IO_CONFIG_REG_BASE
29 
30 /* SFC_IOCFG */
31 #define SFC_MOSI_IO_0_REG		0xec
32 #define SFC_WP_IO_2_REG			0xf0
33 #define SFC_CLK_REG		        0xe8
34 #define SFC_MISO_IO_1_REG		0xe0
35 #define SFC_HOLD_IO_3_REG		0xe4
36 #define SFC_CS_0_N_REG			0xf4
37 
hi3521dv200_io_config_spi_sfc(void)38 static void hi3521dv200_io_config_spi_sfc(void)
39 {
40     /* set pad ctrl reg for spi */
41     writel(0xd0, REG_IO_BASE_FMC + SFC_MOSI_IO_0_REG);    /* sfc_mosi_io0 */
42     writel(0xd0, REG_IO_BASE_FMC + SFC_WP_IO_2_REG);      /* sfc_wp_io2 */
43     writel(0x2b0, REG_IO_BASE_FMC + SFC_CLK_REG);		  /* sfc_clk */
44     writel(0xd0, REG_IO_BASE_FMC + SFC_MISO_IO_1_REG);    /* sfc_miso_io1 */
45     writel(0xd0, REG_IO_BASE_FMC + SFC_HOLD_IO_3_REG);    /* sfc_hold_io3 */
46     writel(0x60, REG_IO_BASE_FMC + SFC_CS_0_N_REG);		  /* sfc_cs0n */
47 }
48 
49 /*****************************************************************************/
hifmc_set_fmc_system_clock(struct spi_op * op,int clk_en)50 void hifmc_set_fmc_system_clock(struct spi_op *op, int clk_en)
51 {
52 	unsigned int old_val;
53 	unsigned int regval;
54 
55 	old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG);
56 
57 	regval &= ~FMC_CLK_SEL_MASK;
58 
59 	if (op && op->clock) {
60 		regval |= op->clock & FMC_CLK_SEL_MASK;
61 		fmc_pr(DTR_DB, "\t|||*-get the setting clock value: %#x\n",
62 			op->clock);
63 	} else {
64 		regval |= fmc_clk_sel(FMC_CLK_24M); /* Default Clock */
65 		hi3521dv200_io_config_spi_sfc();
66 	}
67 	if (clk_en)
68 		regval |= FMC_CLK_ENABLE;
69 	else
70 		regval &= ~FMC_CLK_ENABLE;
71 
72 	if (regval != old_val) {
73 		fmc_pr(DTR_DB, "\t|||*-setting system clock [%#x]%#x\n",
74 			REG_FMC_CRG, regval);
75 		writel(regval, (CRG_REG_BASE + REG_FMC_CRG));
76 	}
77 }
78 
79 /*****************************************************************************/
hifmc_get_fmc_best_2x_clock(unsigned int * clock)80 void hifmc_get_fmc_best_2x_clock(unsigned int *clock)
81 {
82 	int ix;
83 	unsigned int clk_reg;
84 	unsigned int clk_type;
85 	const char *str[] = {"12", "50", "75", "100"};
86 
87 	unsigned int sys_2x_clk[] = {
88 		clk_2x(24), fmc_clk_sel(FMC_CLK_24M),
89 		clk_2x(100), fmc_clk_sel(FMC_CLK_100M),
90 		clk_2x(150), fmc_clk_sel(FMC_CLK_150M),
91 		clk_2x(200), fmc_clk_sel(FMC_CLK_200M),
92 		0,      0,
93 	};
94 
95 	clk_type = FMC_CLK_24M;
96 	clk_reg = fmc_clk_sel(clk_type);
97 	fmc_pr(QE_DBG, "\t|||*-matching flash clock %d\n", *clock);
98 	for (ix = 0; sys_2x_clk[ix]; ix += _2B) {
99 		if (*clock < sys_2x_clk[ix])
100 			break;
101 		clk_reg = sys_2x_clk[ix + 1];
102 		clk_type = get_fmc_clk_type(clk_reg);
103 		fmc_pr(QE_DBG, "\t||||-select system clock: %sMHz\n",
104 			str[clk_type]);
105 	}
106 #ifdef CONFIG_DTR_MODE_SUPPORT
107 	fmc_pr(DTR_DB, "best system clock for SDR.\n");
108 #endif
109 	fmc_pr(QE_DBG, "\t|||*-matched best system clock: %sMHz\n",
110 		str[clk_type]);
111 	*clock = clk_reg;
112 }
113 
114 #ifdef CONFIG_DTR_MODE_SUPPORT
115 /*****************************************************************************/
hifmc_get_fmc_best_4x_clock(unsigned int * clock)116 void hifmc_get_fmc_best_4x_clock(unsigned int *clock)
117 {
118 	int ix;
119 	unsigned int clk_reg;
120 	unsigned int clk_type;
121 	char *const str[] = {"6", "25", "37.5", "50", "75", "100"};
122 
123 	unsigned int sys_4x_clk[] = {
124 		clk_4x(24), fmc_clk_sel(FMC_CLK_24M),
125 		clk_4x(100), fmc_clk_sel(FMC_CLK_100M),
126 		clk_4x(150), fmc_clk_sel(FMC_CLK_150M),
127 		clk_4x(200), fmc_clk_sel(FMC_CLK_200M),
128 		/* TODO 250M */
129 		clk_4x(300), fmc_clk_sel(FMC_CLK_300M),
130 		clk_4x(400), fmc_clk_sel(FMC_CLK_400M),
131 		0,      0,
132 	};
133 
134 	clk_type = FMC_CLK_24M;
135 	clk_reg = fmc_clk_sel(clk_type);
136 	fmc_pr(DTR_DB, "\t|||*-matching flash clock %d\n", *clock);
137 	for (ix = 0; sys_4x_clk[ix]; ix += _2B) {
138 		if (*clock < sys_4x_clk[ix])
139 			break;
140 		clk_reg = sys_4x_clk[ix + 1];
141 		clk_type = get_fmc_clk_type(clk_reg);
142 		fmc_pr(DTR_DB, "\t||||-select system clock: %sMHz\n",
143 			str[clk_type]);
144 	}
145 	fmc_pr(DTR_DB, "best system clock for DTR.\n");
146 	fmc_pr(DTR_DB, "\t|||*-matched best system clock: %sMHz\n",
147 		str[clk_type]);
148 	*clock = clk_reg;
149 }
150 /*****************************************************************************/
151 #endif/* CONFIG_DTR_MODE_SUPPORT */
152