1 /* all about xtx factory */
2 
3 #include <string.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <pthread.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <hal_timer.h>
10 
11 #include "inter.h"
12 
13 #define NOR_XTX_QE_BIT BIT(1)
14 #define NOR_XTX_WPS_BIT BIT(4)
15 #define NOR_XTX_CMD_READ_SR1 (0x35)
16 #define NOR_XTX_CMD_BLK_LOCK_STATUS (0x3D)
17 #define NOR_XTX_CMD_BLK_LOCK (0x36)
18 #define NOR_XTX_CMD_BLK_UNLOCK (0x39)
19 
20 static struct nor_info idt_xtx[] =
21 {
22     {
23         .model = "xt25f128",
24         .id = {0x0b, 0x40, 0x18},
25         .total_size = SZ_16M,
26         .flag = SUPPORT_GENERAL | SUPPORT_INDIVIDUAL_PROTECT,
27     },
28 };
29 
nor_xtx_read_status1(unsigned char * sr1)30 static int nor_xtx_read_status1(unsigned char *sr1)
31 {
32     int ret;
33     char cmd[1] = {NOR_XTX_CMD_READ_SR1};
34     char reg[2] = {0};
35 
36     ret = nor_transfer(1, cmd, 1, reg, 2);
37     if (ret) {
38         SPINOR_ERR("read xtx status1 register fail\n");
39         return ret;
40     }
41 
42     *sr1 = reg[1];
43     return 0;
44 }
45 
nor_xtx_quad_mode(struct nor_flash * unused)46 static int nor_xtx_quad_mode(struct nor_flash *unused)
47 {
48     int ret;
49     unsigned char sr[2];
50 
51     ret = nor_xtx_read_status1(&sr[1]);
52     if (ret)
53         return ret;
54 
55     if (sr[1] & NOR_XTX_QE_BIT)
56         return 0;
57 
58     sr[1] |= NOR_XTX_QE_BIT;
59 
60     ret = nor_read_status(&sr[0]);
61     if (ret)
62         return ret;
63 
64     ret = nor_write_status(sr, 2);
65     if (ret)
66         return ret;
67 
68     ret = nor_xtx_read_status1(&sr[1]);
69     if (ret)
70         return ret;
71     if (!(sr[1] & NOR_XTX_QE_BIT)) {
72         SPINOR_ERR("set xtx QE failed (0x%x)\n", sr[1]);
73         return -EINVAL;
74     }
75     return 0;
76 }
77 
nor_xtx_set_wps(int wps)78 static int nor_xtx_set_wps(int wps)
79 {
80     int ret;
81     unsigned char sr[2];
82     unsigned char sr1;
83 
84     ret = nor_xtx_read_status1(&sr1);
85     if (ret)
86         return ret;
87 
88     if (wps)
89         sr[1] = sr1 | NOR_XTX_WPS_BIT;
90     else
91         sr[1] = sr1 & ~NOR_XTX_WPS_BIT;
92 
93     if (sr1 == sr[1])
94         return 0;
95 
96     ret = nor_read_status(&sr[0]);
97     if (ret)
98         return ret;
99 
100     ret = nor_write_status(sr, 2);
101     if (ret)
102         return ret;
103 
104     ret = nor_xtx_read_status1(&sr1);
105     if (ret)
106         return ret;
107 
108     if ((sr1 & NOR_XTX_WPS_BIT) != (sr[1] & NOR_XTX_WPS_BIT)) {
109         SPINOR_ERR("set xtx wps %d failed (0x%x)\n", wps, sr1);
110         return -EINVAL;
111     }
112     return 0;
113 }
114 
nor_xtx_init_lock(struct nor_flash * nor)115 static int nor_xtx_init_lock(struct nor_flash *nor)
116 {
117     return nor_xtx_set_wps(true);
118 }
119 
nor_xtx_deinit_lock(struct nor_flash * nor)120 static void nor_xtx_deinit_lock(struct nor_flash *nor)
121 {
122     nor_xtx_set_wps(false);
123 }
124 
nor_xtx_blk_islock(unsigned int addr)125 static bool nor_xtx_blk_islock(unsigned int addr)
126 {
127     int ret;
128     unsigned char tbuf[4], st;
129 
130     tbuf[0] = NOR_XTX_CMD_BLK_LOCK_STATUS;
131     tbuf[1] = addr >> 16;
132     tbuf[2] = addr >> 8;
133     tbuf[3] = addr & 0xFF;
134     ret = nor_transfer(4, tbuf, 4, &st, 1);
135     if (ret)
136         return ret;
137     return st & 0x1 ? true : false;
138 }
139 
nor_xtx_blk_unlock(unsigned int addr)140 static int nor_xtx_blk_unlock(unsigned int addr)
141 {
142     int ret;
143     unsigned char tbuf[4];
144 
145     ret = nor_write_enable();
146     if (ret)
147         return ret;
148 
149     tbuf[0] = NOR_XTX_CMD_BLK_UNLOCK;
150     tbuf[1] = addr >> 16;
151     tbuf[2] = addr >> 8;
152     tbuf[3] = addr & 0xFF;
153     ret = nor_transfer(4, tbuf, 4, NULL, 0);
154     if (ret)
155         return ret;
156     if (nor_xtx_blk_islock(addr) == true)
157         return -EBUSY;
158     return 0;
159 }
160 
nor_xtx_blk_lock(unsigned int addr)161 static int nor_xtx_blk_lock(unsigned int addr)
162 {
163     int ret;
164     unsigned char tbuf[4];
165 
166     ret = nor_write_enable();
167     if (ret)
168         return ret;
169 
170     tbuf[0] = NOR_XTX_CMD_BLK_LOCK;
171     tbuf[1] = addr >> 16;
172     tbuf[2] = addr >> 8;
173     tbuf[3] = addr & 0xFF;
174     ret = nor_transfer(4, tbuf, 4, NULL, 0);
175     if (ret)
176         return ret;
177     if (nor_xtx_blk_islock(addr) == true)
178         return 0;
179     return -EBUSY;
180 }
181 
nor_xtx_lock(struct nor_flash * nor,unsigned int addr,unsigned int len)182 static int nor_xtx_lock(struct nor_flash *nor, unsigned int addr,
183         unsigned int len)
184 {
185     return nor_xtx_blk_lock(addr);
186 }
187 
nor_xtx_unlock(struct nor_flash * nor,unsigned int addr,unsigned int len)188 static int nor_xtx_unlock(struct nor_flash *nor, unsigned int addr,
189         unsigned int len)
190 {
191     return nor_xtx_blk_unlock(addr);
192 }
193 
nor_xtx_islock(struct nor_flash * nor,unsigned int addr,unsigned int len)194 static bool nor_xtx_islock(struct nor_flash *nor, unsigned int addr,
195         unsigned int len)
196 {
197     return nor_xtx_blk_islock(addr);
198 }
199 
200 static struct nor_factory nor_xtx = {
201     .factory = FACTORY_XTX,
202     .idt = idt_xtx,
203     .idt_cnt = sizeof(idt_xtx),
204 
205     .init = NULL,
206     .deinit = NULL,
207     .init_lock = nor_xtx_init_lock,
208     .deinit_lock = nor_xtx_deinit_lock,
209     .lock = nor_xtx_lock,
210     .unlock = nor_xtx_unlock,
211     .islock = nor_xtx_islock,
212     .set_quad_mode = nor_xtx_quad_mode,
213     .set_4bytes_addr = NULL,
214 };
215 
nor_register_factory_xtx(void)216 int nor_register_factory_xtx(void)
217 {
218     return nor_register_factory(&nor_xtx);
219 }
220