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