summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/nand-x1000.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/nand-x1000.h')
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.h213
1 files changed, 213 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h
new file mode 100644
index 0000000000..865feb38c5
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h
@@ -0,0 +1,213 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __NAND_X1000_H__
23#define __NAND_X1000_H__
24
25/* NOTE: this is a very minimal API designed only to support a bootloader.
26 * Not suitable for general data storage. It doesn't have proper support for
27 * partial page writes, access to spare area, etc, which are all necessary
28 * for an effective flash translation layer.
29 */
30
31#include <stdint.h>
32#include <stdbool.h>
33#include <stddef.h>
34
35/* Chip supports quad I/O for page read/write */
36#define NANDCHIP_FLAG_QUAD 0x01
37
38/* Set/clear the BRWD bit when enabling/disabling write protection */
39#define NANDCHIP_FLAG_USE_BRWD 0x02
40
41typedef struct nand_drv nand_drv;
42
43/* Defines some static information about a NAND chip */
44typedef struct nand_chip_data {
45 const char* name; /* Name for debugging purposes */
46 uint8_t mf_id; /* Manufacturer ID */
47 uint8_t dev_id; /* Device ID */
48 uint8_t rowaddr_width; /* Number of bytes in row addresses */
49 uint8_t coladdr_width; /* Number of bytes in column addresses */
50 uint32_t dev_conf; /* Value to write to SFC_DEV_CONF register */
51 uint32_t clock_freq; /* Frequency to switch to after identification */
52 uint32_t block_size; /* Number of pages per eraseblock */
53 uint32_t page_size; /* Number of data bytes per page */
54 uint32_t spare_size; /* Number of spare bytes per page */
55 int flags; /* Various flags */
56} nand_chip_data;
57
58/* Defines high-level operations used to implement the public API.
59 * Chips may need to override operations if the default ones aren't suitable.
60 *
61 * Negative return codes return an error, while zero or positive codes are
62 * considered successful. This allows a function to return meaningful data,
63 * if applicable.
64 */
65typedef struct nand_chip_ops {
66 /* Called once after identifying the chip */
67 int(*open)(nand_drv* d);
68
69 /* Called once when the driver is closed */
70 void(*close)(nand_drv* d);
71
72 /* Read or write a complete page including both main and spare areas. */
73 int(*read_page)(nand_drv* d, uint32_t rowaddr, unsigned char* buf);
74 int(*write_page)(nand_drv* d, uint32_t rowaddr, const unsigned char* buf);
75
76 /* Erase a block. */
77 int(*erase_block)(nand_drv* d, uint32_t blockaddr);
78
79 /* Enable or disable the chip's write protection. */
80 int(*set_wp_enable)(nand_drv* d, bool en);
81
82 /* Perform error correction and detection on a raw page (main + spare).
83 * Return the number of errors detected and corrected, or a negative value
84 * if errors were detected but could not be corrected.
85 */
86 int(*ecc_read)(nand_drv* d, unsigned char* buf);
87
88 /* Generate ECC data for a page. The buffer main area is already filled
89 * and this function should write ECC data into the spare area.
90 */
91 void(*ecc_write)(nand_drv* d, unsigned char* buf);
92} nand_chip_ops;
93
94/* Struct used to list all supported NAND chips in an array */
95typedef struct nand_chip_desc {
96 const nand_chip_data* data;
97 const nand_chip_ops* ops;
98} nand_chip_desc;
99
100/* NAND driver structure. It can be accessed by chip ops, but they must not
101 * modify any fields except for "auxbuf", which is a small buffer that can
102 * be used for commands that need to read/write small amounts of data: often
103 * needed for polling status, etc.
104 */
105struct nand_drv {
106 const nand_chip_ops* chip_ops;
107 const nand_chip_data* chip_data;
108 unsigned char* pagebuf;
109 unsigned char* auxbuf;
110 uint32_t raw_page_size;
111 int flags;
112};
113
114/* Note: sfc_init() must be called prior to nand_open() */
115extern int nand_open(void);
116extern void nand_close(void);
117
118/* Controls device-side write protection registers as well as software lock.
119 * Erase and program operations will fail unless you first enable writes.
120 */
121extern int nand_enable_writes(bool en);
122
123/* Byte-based NAND operations */
124extern int nand_read_bytes(uint32_t byteaddr, int count, void* buf);
125extern int nand_write_bytes(uint32_t byteaddr, int count, const void* buf);
126extern int nand_erase_block(uint32_t byteaddr);
127
128/* NAND command numbers */
129#define NAND_CMD_READ_ID 0x9f
130#define NAND_CMD_WRITE_ENABLE 0x06
131#define NAND_CMD_GET_FEATURE 0x0f
132#define NAND_CMD_SET_FEATURE 0x1f
133#define NAND_CMD_PAGE_READ_TO_CACHE 0x13
134#define NAND_CMD_READ_FROM_CACHE 0x0b
135#define NAND_CMD_READ_FROM_CACHEx4 0x6b
136#define NAND_CMD_PROGRAM_LOAD 0x02
137#define NAND_CMD_PROGRAM_LOADx4 0x32
138#define NAND_CMD_PROGRAM_EXECUTE 0x10
139#define NAND_CMD_BLOCK_ERASE 0xd8
140
141/* NAND device register addresses for GET_FEATURE / SET_FEATURE */
142#define NAND_FREG_PROTECTION 0xa0
143#define NAND_FREG_FEATURE 0xb0
144#define NAND_FREG_STATUS 0xc0
145
146/* Protection register bits */
147#define NAND_FREG_PROTECTION_BRWD 0x80
148#define NAND_FREG_PROTECTION_BP2 0x20
149#define NAND_FREG_PROTECTION_BP1 0x10
150#define NAND_FREG_PROTECTION_BP0 0x80
151/* Mask of BP bits 0-2 */
152#define NAND_FREG_PROTECTION_ALLBP (0x38)
153
154/* Feature register bits */
155#define NAND_FREG_FEATURE_QE 0x01
156
157/* Status register bits */
158#define NAND_FREG_STATUS_OIP 0x01
159#define NAND_FREG_STATUS_WEL 0x02
160#define NAND_FREG_STATUS_E_FAIL 0x04
161#define NAND_FREG_STATUS_P_FAIL 0x08
162
163/* Standard implementations for low-level NAND commands. I'm not aware of any
164 * actual standard governing these, but it seems many vendors follow the same
165 * command numbering, status bits, and behavior so these implementations should
166 * work across a wide variety of chips.
167 *
168 * If adding a new NAND chip which only has a minor deviation from these
169 * standard implementations, consider adding a flag and modifying these
170 * functions to change their behavior based on the flag, instead of writing
171 * a whole new implementation.
172 *
173 * None of these functions are directly called by the high-level driver code,
174 * except for nandcmd_std_read_id(). They can be used to implement higher-level
175 * functions in a device's "nand_chip_ops".
176 */
177extern int nandcmd_read_id(nand_drv* d);
178extern int nandcmd_write_enable(nand_drv* d);
179extern int nandcmd_get_feature(nand_drv* d, int reg);
180extern int nandcmd_set_feature(nand_drv* d, int reg, int val);
181extern int nandcmd_page_read_to_cache(nand_drv* d, uint32_t rowaddr);
182extern int nandcmd_read_from_cache(nand_drv* d, unsigned char* buf);
183extern int nandcmd_program_load(nand_drv* d, const unsigned char* buf);
184extern int nandcmd_program_execute(nand_drv* d, uint32_t rowaddr);
185extern int nandcmd_block_erase(nand_drv* d, uint32_t blockaddr);
186
187/* Table filled with all the standard operations for chips which don't
188 * need to override any operations.
189 */
190extern const nand_chip_ops nand_chip_ops_std;
191
192/* Standard NAND chip ops based on the standard "nandcmd" functions.
193 *
194 * Same advice applies here as there: if it's possible to support minor
195 * chip variations with a flag, modify these functions to do so.
196 */
197extern int nandop_std_open(nand_drv* d);
198extern void nandop_std_close(nand_drv* d);
199extern int nandop_std_read_page(nand_drv* d, uint32_t rowaddr, unsigned char* buf);
200extern int nandop_std_write_page(nand_drv* d, uint32_t rowaddr, const unsigned char* buf);
201extern int nandop_std_erase_block(nand_drv* d, uint32_t blockaddr);
202extern int nandop_std_set_wp_enable(nand_drv* d, bool en);
203
204/* The default ECC implementation is a no-op: reads always succeed without
205 * reporting errors and writes will fill the spare area with '0xff' bytes.
206 *
207 * For chips that support internal ECC, this often works because the chip will
208 * ignore writes to the ECC areas.
209 */
210extern int nandop_ecc_none_read(nand_drv* d, unsigned char* buf);
211extern void nandop_ecc_none_write(nand_drv* d, unsigned char* buf);
212
213#endif /* __NAND_X1000_H__ */