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