• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hifmc100_spi_nand.h"
17 
18 #include "hdf_base.h"
19 #include "hdf_log.h"
20 
21 #define HIFMC_WAIT_DEV_READY_TIMEOUT 0x10000
HifmcCntlrSpinandWaitReadyDefault(struct SpiFlash * spi)22 static int32_t HifmcCntlrSpinandWaitReadyDefault(struct SpiFlash *spi)
23 {
24     struct HifmcCntlr *cntlr = NULL;
25     unsigned char status;
26     int32_t timeout = HIFMC_WAIT_DEV_READY_TIMEOUT;
27     int32_t ret;
28 
29     if (spi == NULL || spi->mtd.cntlr == NULL) {
30         return HDF_ERR_INVALID_OBJECT;
31     }
32     cntlr = spi->mtd.cntlr;
33 
34     while (timeout >= 0) {
35         ret = HifmcCntlrDevFeatureOp(cntlr, spi, true, MTD_SPI_NAND_STATUS_ADDR, &status);
36         if (ret != HDF_SUCCESS) {
37             return ret;
38         }
39         if (!(status & MTD_SPI_SR_WIP_MASK)) {
40             return HDF_SUCCESS;
41         }
42         timeout--;
43     }
44 
45     return HDF_ERR_TIMEOUT;
46 }
47 
HifmcCntlrSpinandWriteEnableDefault(struct SpiFlash * spi)48 static int32_t HifmcCntlrSpinandWriteEnableDefault(struct SpiFlash *spi)
49 {
50     struct HifmcCntlr *cntlr = NULL;
51     unsigned int reg;
52     uint8_t status;
53     int32_t ret;
54 
55     if (spi == NULL || spi->mtd.cntlr == NULL) {
56         return HDF_ERR_INVALID_OBJECT;
57     }
58     cntlr = spi->mtd.cntlr;
59 
60     ret = HifmcCntlrDevFeatureOp(cntlr, spi, true, MTD_SPI_NAND_STATUS_ADDR, &status);
61     if (ret != HDF_SUCCESS) {
62         return ret;
63     }
64 #ifdef MTD_DEBUG
65     HDF_LOGD("%s: read status before we addr[%#x]:0x%x", __func__, MTD_SPI_NAND_STATUS_ADDR, status);
66 #endif
67     if ((status & MTD_SPI_SR_WEL_MASK) != 0) {
68         HDF_LOGD("%s: write enable already set", __func__);
69         return HDF_SUCCESS;
70     }
71 
72     reg = HIFMC_REG_READ(cntlr, HIFMC_GLOBAL_CFG_REG_OFF);
73     if ((reg & HIFMC_GLOBAL_CFG_WP_ENABLE) != 0) {
74         reg &= ~HIFMC_GLOBAL_CFG_WP_ENABLE;
75         HIFMC_REG_WRITE(cntlr, reg, HIFMC_GLOBAL_CFG_REG_OFF);
76     }
77 
78     reg = HIFMC_CMD_CMD1(MTD_SPI_CMD_WREN);
79     HIFMC_REG_WRITE(cntlr, reg, HIFMC_CMD_REG_OFF);
80 
81     reg = HIFMC_OP_CFG_FM_CS(spi->cs);
82     HIFMC_REG_WRITE(cntlr, reg, HIFMC_OP_CFG_REG_OFF);
83 
84     reg = HIFMC_OP_CMD1_EN(1) | HIFMC_OP_REG_OP_START;
85     HIFMC_REG_WRITE(cntlr, reg, HIFMC_OP_REG_OFF);
86 
87     HIFMC_CMD_WAIT_CPU_FINISH(cntlr);
88 
89     ret = HifmcCntlrDevFeatureOp(cntlr, spi, true, MTD_SPI_NAND_STATUS_ADDR, &status);
90     if (ret != HDF_SUCCESS) {
91         return ret;
92     }
93 #ifdef MTD_DEBUG
94     HDF_LOGD("%s: read status after we addr[%#x]:0x%x", __func__, MTD_SPI_NAND_STATUS_ADDR, status);
95 #endif
96 
97 #ifdef MTD_DEBUG
98     HDF_LOGD("%s: write enabled", __func__);
99 #endif
100     return HDF_SUCCESS;
101 }
102 
HifmcCntlrSpinandQeEnableDefault(struct SpiFlash * spi)103 static int32_t HifmcCntlrSpinandQeEnableDefault(struct SpiFlash *spi)
104 {
105     struct HifmcCntlr *cntlr = NULL;
106     uint8_t feature;
107     int32_t ret;
108     int enable;
109 
110     if (spi == NULL || spi->mtd.cntlr == NULL) {
111         return HDF_ERR_INVALID_OBJECT;
112     }
113     cntlr = spi->mtd.cntlr;
114 
115     enable = ((spi->writeCfg.ifType >= MTD_SPI_IF_QUAD) ||
116                 (spi->readCfg.ifType >= MTD_SPI_IF_QUAD)) ? 1 : 0;
117     ret = HifmcCntlrDevFeatureOp(cntlr, spi, true, MTD_SPI_NAND_FEATURE_ADDR, &feature);
118     if (ret != HDF_SUCCESS) {
119         return ret;
120     }
121     if (!!(feature & MTD_SPI_FEATURE_QE_ENABLE) == enable) {
122         HDF_LOGI("%s: qe feature:%d, qe enable:%d", __func__, feature, enable);
123         return HDF_SUCCESS;
124     }
125 
126     if (enable == 1) {
127         feature |= MTD_SPI_FEATURE_QE_ENABLE;
128     } else {
129         feature &= ~MTD_SPI_FEATURE_QE_ENABLE;
130     }
131 #ifdef MTD_DEBUG
132     HDF_LOGD("%s: spi nand %s quad", __func__, enable == 1 ? "enable" : "disable");
133 #endif
134     ret = HifmcCntlrDevFeatureOp(cntlr, spi, false, MTD_SPI_NAND_FEATURE_ADDR, &feature);
135     if (ret != HDF_SUCCESS) {
136         return ret;
137     }
138 
139     SpiFlashWaitReady(spi);
140     ret = HifmcCntlrDevFeatureOp(cntlr, spi, true, MTD_SPI_NAND_FEATURE_ADDR, &feature);
141     if (ret != HDF_SUCCESS) {
142         return ret;
143     }
144     if (!!(feature & MTD_SPI_FEATURE_QE_ENABLE) == enable) {
145         HDF_LOGD("%s: spi nand %s quad success", __func__, enable == 1 ? "enable" : "disable");
146         return HDF_SUCCESS;
147     } else {
148         HDF_LOGE("%s: spi nand %s quad failed", __func__, enable == 1 ? "enable" : "disable");
149         return HDF_ERR_IO;
150     }
151 }
152 
HifmcCntlrSpinandQeNotEnable(struct SpiFlash * spi)153 static int32_t HifmcCntlrSpinandQeNotEnable(struct SpiFlash *spi)
154 {
155     (void)spi;
156     return HDF_SUCCESS;
157 }
158 
159 static struct MtdSpiOps g_spiOpsDefault = {
160     .waitReady = HifmcCntlrSpinandWaitReadyDefault,
161     .writeEnable = HifmcCntlrSpinandWriteEnableDefault,
162     .qeEnable = HifmcCntlrSpinandQeEnableDefault,
163 };
164 
165 static struct SpiOpsInfo g_spiInfoTable[] = {
166     {
167         .id    = {0x2c, 0x14}, // MT29f2G01ABA
168         .idLen = 2,
169         .spiOps = {
170             .qeEnable = HifmcCntlrSpinandQeNotEnable,
171         },
172     },
173     {
174         .id    = {0x2c, 0x25}, // MT29f2G01ABB
175         .idLen = 2,
176         .spiOps = {
177             .qeEnable = HifmcCntlrSpinandQeNotEnable,
178         },
179     },
180 };
181 
SpinandGetSpiOps(struct SpiFlash * spi)182 int32_t SpinandGetSpiOps(struct SpiFlash *spi)
183 {
184     size_t i;
185 
186     if (spi == NULL) {
187         return HDF_ERR_INVALID_OBJECT;
188     }
189     spi->spiOps = g_spiOpsDefault;
190 
191     for (i = 0; i < (sizeof(g_spiInfoTable) / sizeof(g_spiInfoTable[0])); i++) {
192         if (memcmp(spi->mtd.id, g_spiInfoTable[i].id, g_spiInfoTable[i].idLen) != 0) {
193             continue;
194         }
195         if (g_spiInfoTable[i].spiOps.waitReady != NULL) {
196             spi->spiOps.waitReady = g_spiInfoTable[i].spiOps.waitReady;
197         }
198         if (g_spiInfoTable[i].spiOps.writeEnable != NULL) {
199             spi->spiOps.writeEnable = g_spiInfoTable[i].spiOps.writeEnable;
200         }
201         if (g_spiInfoTable[i].spiOps.qeEnable != NULL) {
202             spi->spiOps.qeEnable = g_spiInfoTable[i].spiOps.qeEnable;
203         }
204         break;
205     }
206     return HDF_SUCCESS;
207 }
208