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.h207
1 files changed, 141 insertions, 66 deletions
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h
index cc56b836f8..711bf190b5 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h
@@ -22,86 +22,161 @@
22#ifndef __NAND_X1000_H__ 22#ifndef __NAND_X1000_H__
23#define __NAND_X1000_H__ 23#define __NAND_X1000_H__
24 24
25/* NOTE: this is a very minimal API designed only to support a bootloader. 25#include <stdint.h>
26 * Not suitable for general data storage. It doesn't have proper support for 26#include <stddef.h>
27 * partial page writes, access to spare area, etc, which are all necessary 27#include <stdbool.h>
28 * for an effective flash translation layer. 28#include "kernel.h"
29
30#define NAND_SUCCESS 0
31#define NAND_ERR_UNKNOWN_CHIP (-1)
32#define NAND_ERR_PROGRAM_FAIL (-2)
33#define NAND_ERR_ERASE_FAIL (-3)
34#define NAND_ERR_UNALIGNED (-4)
35
36/* keep max page size in sync with the NAND chip table in the .c file */
37#define NAND_DRV_SCRATCHSIZE 32
38#define NAND_DRV_MAXPAGESIZE 2112
39
40/* Quad I/O support bit */
41#define NAND_CHIPFLAG_QUAD 0x0001
42/* Chip requires QE bit set to enable quad I/O mode */
43#define NAND_CHIPFLAG_HAS_QE_BIT 0x0002
44
45/* Types to distinguish between block & page addresses in the API.
29 * 46 *
30 * There's no ECC support. This can be added if necessary, but it's unlikely 47 * BIT 31 log2_ppb bits
31 * the boot area on any X1000 device uses software ECC as Ingenic's SPL simply 48 * +-------------------------------+---------------+
32 * doesn't have much room for more code (theirs programmed to work on multiple 49 * nand_page_t = | block nr | page nr |
33 * hardware configurations, so it's bigger than ours). 50 * +-------------------------------+---------------+
51 * BIT 0
52 *
53 * The page address is split into block and page numbers. Page numbers occupy
54 * the lower log2_ppb bits, and the block number occupies the upper bits.
55 *
56 * Block addresses are structured the same as page addresses, but with a page
57 * number of 0. So block number N has address N << log2_ppb.
34 */ 58 */
59typedef uint32_t nand_block_t;
60typedef uint32_t nand_page_t;
35 61
36#include <stdint.h> 62typedef struct nand_chip {
37#include <stdbool.h> 63 /* Manufacturer and device ID bytes */
38#include <stddef.h> 64 uint8_t mf_id;
65 uint8_t dev_id;
39 66
40/* Error codes which can be returned by the NAND API */ 67 /* Row/column address width */
41#define NAND_SUCCESS 0 68 uint8_t row_cycles;
42#define NAND_ERR_UNKNOWN_CHIP (-1) 69 uint8_t col_cycles;
43#define NAND_ERR_UNALIGNED (-2)
44#define NAND_ERR_WRITE_PROTECT (-3)
45#define NAND_ERR_CONTROLLER (-4)
46#define NAND_ERR_COMMAND (-5)
47 70
48/* Chip supports quad I/O for page read/write */ 71 /* Base2 logarithm of the number of pages per block */
49#define NANDCHIP_FLAG_QUAD 0x01 72 unsigned log2_ppb;
50 73
51/* Set/clear the BRWD bit when enabling/disabling write protection */ 74 /* Size of a page's main / oob areas, in bytes. */
52#define NANDCHIP_FLAG_USE_BRWD 0x02 75 unsigned page_size;
76 unsigned oob_size;
53 77
54typedef struct nand_chip_data { 78 /* Total number of blocks in the chip */
55 /* Chip manufacturer / device ID */ 79 unsigned nr_blocks;
56 uint8_t mf_id;
57 uint8_t dev_id;
58 80
59 /* Width of row/column addresses in bytes */ 81 /* Clock frequency to use */
60 uint8_t rowaddr_width; 82 uint32_t clock_freq;
61 uint8_t coladdr_width;
62 83
63 /* SFC dev conf and clock frequency to use for this device */ 84 /* Value of sfc_dev_conf */
64 uint32_t dev_conf; 85 uint32_t dev_conf;
65 uint32_t clock_freq;
66 86
67 /* Page size in bytes = 1 << log2_page_size */ 87 /* Chip specific flags */
68 uint32_t log2_page_size; 88 uint32_t flags;
89} nand_chip;
90
91typedef struct nand_drv {
92 /* NAND access lock. Needs to be held during any operations. */
93 struct mutex mutex;
94
95 /* Reference count for open/close operations */
96 unsigned refcount;
97
98 /* Scratch and page buffers. Both need to be cacheline-aligned and are
99 * provided externally by the caller prior to nand_open().
100 *
101 * - The scratch buffer is NAND_DRV_SCRATCHSIZE bytes long and is used
102 * for small data transfers associated with commands. It must not be
103 * disturbed while any NAND operation is in progress.
104 *
105 * - The page buffer is used by certain functions like nand_read_bytes(),
106 * but it's main purpose is to provide a common temporary buffer for
107 * driver users to perform I/O with. Must be fpage_size bytes long.
108 */
109 uint8_t* scratch_buf;
110 uint8_t* page_buf;
111
112 /* Pointer to the chip data. */
113 const nand_chip* chip;
114
115 /* Pages per block = 1 << chip->log2_ppb */
116 unsigned ppb;
117
118 /* Full page size = chip->page_size + chip->oob_size */
119 unsigned fpage_size;
120
121 /* Probed mf_id / dev_id for debugging, in case identification fails. */
122 uint8_t mf_id;
123 uint8_t dev_id;
124
125 /* SFC commands used for I/O, these are set based on chip data */
126 uint32_t cmd_page_read;
127 uint32_t cmd_read_cache;
128 uint32_t cmd_program_load;
129 uint32_t cmd_program_execute;
130 uint32_t cmd_block_erase;
131} nand_drv;
132
133extern const nand_chip supported_nand_chips[];
134extern const size_t nr_supported_nand_chips;
135
136/* Return the static NAND driver instance.
137 *
138 * ALL normal Rockbox code should use this instance. The SPL does not
139 * use it, because it needs to manually place buffers in external RAM.
140 */
141extern nand_drv* nand_init(void);
142
143static inline void nand_lock(nand_drv* drv)
144{
145 mutex_lock(&drv->mutex);
146}
69 147
70 /* Block size in number of pages = 1 << log2_block_size */ 148static inline void nand_unlock(nand_drv* drv)
71 uint32_t log2_block_size; 149{
150 mutex_unlock(&drv->mutex);
151}
72 152
73 /* Chip flags */ 153/* Open or close the NAND driver
74 uint32_t flags; 154 *
75} nand_chip_data; 155 * The NAND driver is reference counted, and opening / closing it will
156 * increment and decrement the reference count. The hardware is only
157 * controlled when the reference count rises above or falls to 0, else
158 * these functions are no-ops which always succeed.
159 *
160 * These functions require the lock to be held.
161 */
162extern int nand_open(nand_drv* drv);
163extern void nand_close(nand_drv* drv);
164
165/* Read / program / erase operations. Buffer needs to be cache-aligned for DMA.
166 * Read and program operate on full page data, ie. including OOB data areas.
167 *
168 * NOTE: ECC is not implemented. If it ever needs to be, these functions will
169 * probably use ECC transparently. All code should be written to expect this.
170 */
171extern int nand_block_erase(nand_drv* drv, nand_block_t block);
172extern int nand_page_program(nand_drv* drv, nand_page_t page, const void* buffer);
173extern int nand_page_read(nand_drv* drv, nand_page_t page, void* buffer);
76 174
77/* Open or close the NAND driver. The NAND driver takes control of the SFC, 175/* Wrappers to read/write bytes. For simple access to the main data area only.
78 * so that driver must be in the closed state before opening the NAND driver. 176 * The write address / length must align to a block boundary. Reads do not have
177 * any alignment requirement. OOB data is never read, and is written as 0xff.
79 */ 178 */
80extern int nand_open(void); 179extern int nand_read_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void* buffer);
81extern void nand_close(void); 180extern int nand_write_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, const void* buffer);
82
83/* Identify the NAND chip. This must be done after opening the driver and
84 * prior to any data access, in order to set the chip parameters. */
85extern int nand_identify(int* mf_id, int* dev_id);
86
87/* Return the chip data for the identified NAND chip.
88 * Returns NULL if the chip is not identified. */
89const nand_chip_data* nand_get_chip_data(void);
90
91/* Controls the chip's write protect features. The driver also keeps track of
92 * this flag and refuses to perform write or erase operations unless you have
93 * enabled writes. Writes should be disabled again when you finish writing. */
94extern int nand_enable_writes(bool en);
95
96/* Reading and writing operates on whole pages at a time. If the address or
97 * size is not aligned to a multiple of the page size, no data will be read
98 * or written and an error code is returned. */
99extern int nand_read(uint32_t addr, uint32_t size, uint8_t* buf);
100extern int nand_write(uint32_t addr, uint32_t size, const uint8_t* buf);
101
102/* Erase operates on whole blocks. Like the page read/write operations,
103 * the address and size must be aligned to a multiple of the block size.
104 * If not, no blocks are erased and an error code is returned. */
105extern int nand_erase(uint32_t addr, uint32_t size);
106 181
107#endif /* __NAND_X1000_H__ */ 182#endif /* __NAND_X1000_H__ */