1 /*
2 * hifmc100_spi_issi.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 #define SPI_NOR_ISSI_QE_SHIFT 6
24 #define SPI_NOR_ISSI_SRWD_MASK (1 << 7)
25 #define SPI_NOR_ISSI_QE_MASK (1 << SPI_NOR_ISSI_QE_SHIFT)
26 #define spi_nor_issi_get_qe(sr) (((sr) & SPI_NOR_ISSI_QE_MASK) \
27 >> SPI_NOR_ISSI_QE_SHIFT)
28
spi_issi_set_cmd(struct hifmc_spi * spi)29 static void spi_issi_set_cmd(struct hifmc_spi *spi)
30 {
31 unsigned int reg;
32 struct hifmc_host *host = (struct hifmc_host *)spi->host;
33
34 reg = fmc_cmd_cmd1(SPI_CMD_WRSR);
35 hifmc_write(host, FMC_CMD, reg);
36 fmc_pr(QE_DBG, "\t|-Set CMD[%#x]%#x\n", FMC_CMD, reg);
37
38 reg = op_cfg_fm_cs(spi->chipselect) | OP_CFG_OEN_EN;
39 hifmc_write(host, FMC_OP_CFG, reg);
40 fmc_pr(QE_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
41
42 reg = fmc_data_num_cnt(SPI_NOR_SR_LEN);
43 hifmc_write(host, FMC_DATA_NUM, reg);
44 fmc_pr(QE_DBG, "\t|-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg);
45
46 reg = fmc_op_cmd1_en(ENABLE) |
47 fmc_op_write_data_en(ENABLE) |
48 FMC_OP_REG_OP_START;
49 hifmc_write(host, FMC_OP, reg);
50 fmc_pr(QE_DBG, "\t|-Set OP[%#x]%#x\n", FMC_OP, reg);
51
52 fmc_cmd_wait_cpu_finish(host);
53 }
54
spi_issi_qe_enable(struct hifmc_spi * spi)55 static int spi_issi_qe_enable(struct hifmc_spi *spi)
56 {
57 unsigned char config;
58 unsigned char op;
59
60 const char *str[] = {"Disable", "Enable"};
61 struct hifmc_host *host = (struct hifmc_host *)spi->host;
62
63 op = spi_is_quad(spi);
64
65 fmc_pr(QE_DBG, "\t*-Start SPI Nor %s Quad.\n", str[op]);
66
67 config = spi_general_get_flash_register(spi, SPI_CMD_RDSR);
68 fmc_pr(QE_DBG, "\t|-Read Config Register[%#x]%#x\n", SPI_CMD_RDSR,
69 config);
70 if (op == spi_nor_issi_get_qe(config)) {
71 fmc_pr(QE_DBG, "\t* Quad was %sd, config:%#x\n", str[op],
72 config);
73 return op;
74 }
75
76 spi->driver->write_enable(spi);
77
78 config = spi_general_get_flash_register(spi, SPI_CMD_RDSR);
79 config &= ~SPI_NOR_ISSI_SRWD_MASK;
80
81 if (op)
82 config |= SPI_NOR_ISSI_QE_MASK;
83 else
84 config &= ~SPI_NOR_ISSI_QE_MASK;
85 writeb(config, host->iobase);
86 fmc_pr(QE_DBG, "\t|-Write IO[%p]%#x\n", host->iobase,
87 *(unsigned short *)host->iobase);
88
89 spi_issi_set_cmd(spi);
90
91 spi->driver->wait_ready(spi);
92
93 config = spi_general_get_flash_register(spi, SPI_CMD_RDSR);
94 if (op == spi_nor_issi_get_qe(config)) {
95 fmc_pr(QE_DBG, "\t|-%s Quad success, config: %#x\n", str[op],
96 config);
97 } else {
98 db_msg("Error: %s Quad failed! reg: %#x\n", str[op], config);
99 }
100
101 fmc_pr(QE_DBG, "\t* End SPI Nor %s Quad.\n", str[op]);
102
103 return op;
104 }
105
106