1 /*
2 * hifmc100_spi_micron.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 /*****************************************************************************/
24 #define SPI_CMD_FIRST_RESET_4ADDR 0x66
25 #define SPI_CMD_SECOND_RESET_4ADDR 0x99
26
27 #define SPI_CMD_FLAG_SR_MICRON 0x70 /* READ FLAG STATUS REGISTER */
28 #define SPI_CMD_RD_RDCR_MICRON 0xB5 /* READ NONVOLATILE CONFIGURATION
29 REGISTER */
30 #define SPI_CMD_WR_RDCR_MICRON 0xB1 /* WRITE NONVOLATILE CONFIGURATION
31 REGISTER */
32 #define SPI_NOR_ADS_MASK 0x1
33 #define spi_nor_get_4byte_by_flag_sr(sr) ((sr) & SPI_NOR_ADS_MASK)
34
35 #define spi_nor_ads_set_4byte(cr) ((cr) & (~SPI_NOR_ADS_MASK))
36 #define spi_nor_ads_get_4byte(cr) ((cr) & SPI_NOR_ADS_MASK)
37 /****************************************************************************/
spi_micron_entry_4addr(struct hifmc_spi * spi,int enable)38 static int spi_micron_entry_4addr(struct hifmc_spi *spi, int enable)
39 {
40 unsigned char status;
41 unsigned int reg;
42 const char *str[] = {"Disable", "Enable"};
43 struct hifmc_host *host = (struct hifmc_host *)spi->host;
44
45 fmc_pr(AC_DBG, "\t* Start SPI Nor %s 4-byte mode.\n",
46 str[enable]);
47
48 if (spi->addrcycle != SPI_NOR_4BYTE_ADDR_LEN) {
49 fmc_pr(AC_DBG, "\t* Not support 4B mode.\n");
50 return 0;
51 }
52
53 status = spi_general_get_flash_register(spi, SPI_CMD_FLAG_SR_MICRON);
54 fmc_pr(AC_DBG, "\t Read flag status register[%#x]:%#x\n",
55 SPI_CMD_FLAG_SR_MICRON, status);
56 if (spi_nor_get_4byte_by_flag_sr(status) == enable) {
57 fmc_pr(AC_DBG, "\t* 4-byte was %sd, reg:%#x\n", str[enable],
58 status);
59 return 0;
60 }
61
62 spi->driver->write_enable(spi);
63
64 if (enable)
65 reg = SPI_CMD_EN4B;
66 else
67 reg = SPI_CMD_EX4B;
68 hifmc_write(host, FMC_CMD, fmc_cmd_cmd1(reg));
69 fmc_pr(AC_DBG, "\t Set CMD[%#x]%#x\n", FMC_CMD, reg);
70
71 reg = op_cfg_fm_cs(spi->chipselect) | OP_CFG_OEN_EN;
72 hifmc_write(host, FMC_OP_CFG, reg);
73 fmc_pr(AC_DBG, "\t Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
74
75 reg = fmc_op_cmd1_en(ENABLE) | FMC_OP_REG_OP_START;
76 hifmc_write(host, FMC_OP, reg);
77 fmc_pr(AC_DBG, "\t Set OP[%#x]%#x\n", FMC_OP, reg);
78
79 fmc_cmd_wait_cpu_finish(host);
80
81 spi->driver->wait_ready(spi);
82
83 status = spi_general_get_flash_register(spi,
84 SPI_CMD_FLAG_SR_MICRON);
85 fmc_pr(AC_DBG, "\t Read flag status register[%#x]:%#x\n",
86 SPI_CMD_FLAG_SR_MICRON, status);
87 if (spi_nor_get_4byte_by_flag_sr(status) != enable) {
88 db_msg("Error: %s 4-byte failed! SR3:%#x\n",
89 str[enable], status);
90 return status;
91 }
92
93 fmc_pr(AC_DBG, "\t %s 4-byte success, SR3:%#x\n", str[enable], status);
94 fmc_pr(AC_DBG, "\t* End SPI Nor flash %s 4-byte mode.\n", str[enable]);
95
96 return 0;
97 }
98