commit | author | age
|
8df7c2
|
1 |
/********************************************************************************* |
G |
2 |
* Copyright: (C) 2023 LingYun IoT System Studio. All Rights Reserved. |
|
3 |
* Author: Guo Wenxue <guowenxue@gmail.com> |
|
4 |
* |
|
5 |
* Description: This file is W25Qxx SPI Norflash driver on RaspberryPi 40Pin. |
|
6 |
* |
|
7 |
* W25QXX RaspberryPi 40Pin |
|
8 |
* VCC <---> 3.3V(Pin#1) |
|
9 |
* CS <---> CS(Pin#24) |
|
10 |
* DO <---> MISO(Pin#21) |
|
11 |
* GND <---> GND(Pin#9) |
|
12 |
* CLK <---> SCLK(Pin#23) |
|
13 |
* DI <---> MOSI(Pin#19) |
|
14 |
* |
|
15 |
********************************************************************************/ |
|
16 |
|
|
17 |
#ifndef _W25QFLASH_H |
|
18 |
#define _W25QFLASH_H |
|
19 |
|
|
20 |
#include <stdbool.h> |
|
21 |
|
|
22 |
#define _W25QXX_DEBUG 1 |
|
23 |
|
|
24 |
/* Flash opcodes. Refer to <<W25Q256JV.pdf>> P26 Table 8.1.2 Instruction Set Table */ |
|
25 |
#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ |
|
26 |
#define SPINOR_OP_RDUID 0x4b /* Read unique ID */ |
|
27 |
#define SPINOR_OP_WRSR1 0x01 /* Write status register-1 */ |
|
28 |
#define SPINOR_OP_WRSR2 0x31 /* Write status register-2 */ |
|
29 |
#define SPINOR_OP_WRSR3 0x11 /* Write status register-3 */ |
|
30 |
#define SPINOR_OP_BP 0x02 /* Byte program */ |
|
31 |
#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ |
|
32 |
#define SPINOR_OP_WRDI 0x04 /* Write disable */ |
|
33 |
#define SPINOR_OP_RDSR1 0x05 /* Read status register-1 */ |
|
34 |
#define SPINOR_OP_RDSR2 0x35 /* Read status register-2 */ |
|
35 |
#define SPINOR_OP_RDSR3 0x15 /* Read status register-3 */ |
|
36 |
#define SPINOR_OP_WREN 0x06 /* Write enable */ |
|
37 |
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ |
|
38 |
#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */ |
|
39 |
|
|
40 |
#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ |
|
41 |
#define SPINOR_OP_BE_4K_4B 0xdc /* Block erase (64KiB) with 4-Byte Address */ |
|
42 |
#define SPINOR_OP_BE_4K 0xd8 /* Block erase (64KiB) */ |
|
43 |
#define SPINOR_OP_SE_4B 0x21 /* Sector erase (4KiB) with 4-Byte Address */ |
|
44 |
#define SPINOR_OP_SE 0x20 /* Sector erase (4KiB) */ |
|
45 |
#define SPINOR_OP_PP_4B 0x12 /* Page Program (up to 256 bytes) with 4-Byte Address */ |
|
46 |
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ |
|
47 |
#define SPINOR_OP_SRSTEN 0x66 /* Software Reset Enable */ |
|
48 |
#define SPINOR_OP_SRST 0x99 /* Software Reset */ |
|
49 |
|
|
50 |
typedef struct spi_info |
|
51 |
{ |
|
52 |
int hspi; /* SPI device description */ |
|
53 |
|
|
54 |
void (*select)(struct spi_info *spi); /* CS enable function */ |
|
55 |
void (*deselect)(struct spi_info *spi); /* CS disable function */ |
|
56 |
void (*xcmd)(struct spi_info *spi, uint8_t command); /* Send a byte command */ |
|
57 |
void (*xfer)(struct spi_info *spi, uint8_t *send_buf, uint8_t *recv_buf, int bytes); /* Transmit and Receive N byte */ |
|
58 |
} spi_info_t; |
|
59 |
|
|
60 |
typedef struct flash_info |
|
61 |
{ |
|
62 |
char *name; /* Chip name */ |
|
63 |
uint32_t jedec_id; /* JEDEC ID, 3 bytes */ |
|
64 |
uint64_t capacity; /* Chip size in bytes */ |
|
65 |
uint32_t block_size; /* Block size in bytes */ |
|
66 |
uint32_t sector_size; /* Sector size in bytes */ |
|
67 |
uint32_t page_size; /* Page size in bytes */ |
|
68 |
uint32_t n_blocks; /* Number of blocks */ |
|
69 |
uint32_t n_sectors; /* Number of sectors */ |
|
70 |
uint32_t n_pages; /* Number of pages */ |
|
71 |
} flash_info_t; |
|
72 |
|
|
73 |
|
|
74 |
typedef struct spinor_info |
|
75 |
{ |
|
76 |
spi_info_t *spi; |
|
77 |
flash_info_t *flash; |
|
78 |
uint8_t lock; |
|
79 |
} spinor_info_t; |
|
80 |
|
|
81 |
|
|
82 |
/* Status registers */ |
|
83 |
enum |
|
84 |
{ |
|
85 |
REG_STATUS1, |
|
86 |
REG_STATUS2, |
|
87 |
REG_STATUS3, |
|
88 |
REG_STATUS_MAX, |
|
89 |
}; |
|
90 |
|
|
91 |
/*+-------------------------------+ |
|
92 |
*| SPI Norflash HighLevel API | |
|
93 |
*+-------------------------------+*/ |
|
94 |
|
|
95 |
/* SPI Norflash API test function */ |
|
96 |
extern void spinor_test(void); |
|
97 |
|
|
98 |
/* Initial SPI and detect the flash chip */ |
|
99 |
extern int spinor_init(struct spinor_info *spinor); |
|
100 |
|
|
101 |
/* Description: Erase whole flash chip. |
|
102 |
* Reference : P60, 8.2.32 Chip Erase (C7h / 60h) |
|
103 |
*/ |
|
104 |
extern int spinor_erase_chip(struct spinor_info *spinor); |
|
105 |
|
|
106 |
/* Description: Erase blocks by 64KiB, |
|
107 |
* Reference : P59, 8.2.31 64KB Block Erase with 4-Byte Address (DCh) |
|
108 |
* @address is the erase start physical address, which can be not block alignment such as 0x10001. |
|
109 |
* @size is the erase size, which can be larger than a block such as 4097, and it will erase 2 blocks; |
|
110 |
*/ |
|
111 |
extern int spinor_erase_block(struct spinor_info *spinor, uint32_t address, uint32_t size); |
|
112 |
|
|
113 |
/* Description: Erase sectors by 4KiB |
|
114 |
* Reference : P56, 8.2.28 Sector Erase with 4-Byte Address (21h) |
|
115 |
* @address is the erase start physical address, which can be not sector alignment such as 0x1001. |
|
116 |
* @size is the erase size, which can be larger than a sector such as 4097, and it will erase 2 sectors; |
|
117 |
*/ |
|
118 |
extern int spinor_erase_sector(struct spinor_info *spinor, uint32_t address, uint32_t size); |
|
119 |
|
|
120 |
/* Description: Page random write by 256B |
|
121 |
* @addr is the write start physical address, which can be not page alignment such as 0x101. |
|
122 |
* @size is the write size, which can be larger than a page such as 257, and it will write 2 pages; |
|
123 |
*/ |
|
124 |
extern int spinor_write(struct spinor_info *spinor, uint32_t address, uint8_t *data, uint32_t bytes); |
|
125 |
|
|
126 |
/* Description: The Fast Read instruction can read the entire memory chip. |
|
127 |
* Reference : P41, 8.2.13 Fast Read with 4-Byte Address (0Ch) |
|
128 |
* @address is the read start physical address, which can be not page alignment such as 0x101. |
|
129 |
* @size is the read size, which can be larger than a page such as 257, and it will read 2 pages; |
|
130 |
*/ |
|
131 |
extern int spinor_read(struct spinor_info *spinor, uint32_t address, uint8_t *buf, uint32_t bytes); |
|
132 |
|
|
133 |
/*+-------------------------------+ |
|
134 |
*| SPI Norflash LowLevel API | |
|
135 |
*+-------------------------------+*/ |
|
136 |
|
|
137 |
/* Detect the norflash by JEDEC ID */ |
|
138 |
int spinor_detect_by_jedec(struct spinor_info *spinor); |
|
139 |
|
|
140 |
/* Description: Read the chipset UNIQUE ID. |
|
141 |
* Reference : P68, 8.2.40 Read Unique ID Number (4Bh) |
|
142 |
*/ |
|
143 |
int spinor_read_uniqid(struct spi_info *spi, uint8_t *uniq_id); |
|
144 |
|
|
145 |
/* Description: Read the chipset JEDEC ID. |
|
146 |
* Reference : P69, 8.2.41 Read JEDEC ID (9Fh) |
|
147 |
*/ |
|
148 |
uint32_t spinor_read_jedecid(struct spi_info *spi); |
|
149 |
|
|
150 |
/* Description: Write Enable |
|
151 |
* Reference : P31, 8.2.1 Write Enable (06h) |
|
152 |
*/ |
|
153 |
void spinor_write_enable(struct spi_info *spi); |
|
154 |
|
|
155 |
/* Description: Write Disable |
|
156 |
* Reference : P32, 8.2.3 Write Disable (04h) |
|
157 |
*/ |
|
158 |
void spinor_write_disable(struct spi_info *spi); |
|
159 |
|
|
160 |
/* Description: Read Status Register |
|
161 |
* Reference : P32, 8.2.4 Read Status Register-1 (05h), Status Register-2 (35h) & Status Register-3 (15h) |
|
162 |
*/ |
|
163 |
uint8_t spinor_read_status_reg(struct spi_info *spi, uint8_t reg); |
|
164 |
|
|
165 |
/* Description: Write Status Register |
|
166 |
* Reference : P33, 8.2.5 Write Status Register-1 (01h), Status Register-2 (31h) & Status Register-3 (11h) |
|
167 |
*/ |
|
168 |
void spinor_write_status_reg(struct spi_info *spi, uint8_t reg, uint8_t value); |
|
169 |
|
|
170 |
/* Description: Wait flash program/erase finished by read Status Register for BUSY bit |
|
171 |
* Reference : P15, 7.1 Status Registers |
|
172 |
*/ |
|
173 |
void spinor_WaitForWriteEnd(struct spi_info *spi); |
|
174 |
|
|
175 |
#endif |