summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/sfc-x1000.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/sfc-x1000.h')
-rw-r--r--firmware/target/mips/ingenic_x1000/sfc-x1000.h152
1 files changed, 86 insertions, 66 deletions
diff --git a/firmware/target/mips/ingenic_x1000/sfc-x1000.h b/firmware/target/mips/ingenic_x1000/sfc-x1000.h
index 5784198b93..d28bcb6740 100644
--- a/firmware/target/mips/ingenic_x1000/sfc-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/sfc-x1000.h
@@ -19,87 +19,107 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#ifndef __SFC_X1000_H__
23#define __SFC_X1000_H__
24
25#include "x1000/sfc.h"
22#include <stdint.h> 26#include <stdint.h>
23#include <stdbool.h> 27#include <stdbool.h>
24#include "clk-x1000.h"
25#include "x1000/sfc.h"
26 28
27/* SPI flash controller interface -- this is a low-level driver upon which 29/* SPI transfer mode. SFC_TMODE_X_Y_Z means:
28 * you can build NAND/NOR flash drivers. The main function is sfc_exec(), 30 *
29 * used to issue commands, transfer data, etc. 31 * - X lines for command phase
32 * - Y lines for address+dummy phase
33 * - Z lines for data phase
30 */ 34 */
35#define SFC_TMODE_1_1_1 0
36#define SFC_TMODE_1_1_2 1
37#define SFC_TMODE_1_2_2 2
38#define SFC_TMODE_2_2_2 3
39#define SFC_TMODE_1_1_4 4
40#define SFC_TMODE_1_4_4 5
41#define SFC_TMODE_4_4_4 6
31 42
32#define SFC_FLAG_READ 0x01 /* Read data */ 43/* Phase format
33#define SFC_FLAG_WRITE 0x02 /* Write data */ 44 * _____________________
34#define SFC_FLAG_DUMMYFIRST 0x04 /* Do dummy bits before sending address. 45 * / SFC_PFMT_ADDR_FIRST \
35 * Default is dummy bits after address. 46 * +-----+-------+-------+------+
36 */ 47 * | cmd | addr | dummy | data |
48 * +-----+-------+-------+------+
49 * ______________________
50 * / SFC_PFMT_DUMMY_FIRST \
51 * +-----+-------+-------+------+
52 * | cmd | dummy | addr | data |
53 * +-----+-------+-------+------+
54 */
55#define SFC_PFMT_ADDR_FIRST 0
56#define SFC_PFMT_DUMMY_FIRST 1
37 57
38/* SPI transfer mode. If in doubt, check with the X1000 manual and confirm 58/* Direction of transfer flag */
39 * the transfer format is what you expect. 59#define SFC_READ 0
60#define SFC_WRITE (1 << 31)
61
62/** \brief Macro to generate an SFC command for use with sfc_exec()
63 * \param cmd Command number (up to 16 bits)
64 * \param tmode SPI transfer mode
65 * \param awidth Number of address bytes
66 * \param dwidth Number of dummy cycles (1 cycle = 1 bit)
67 * \param pfmt Phase format (address first or dummy first)
68 * \param data_en 1 to enable data phase, 0 to omit it
40 */ 69 */
41#define SFC_MODE_STANDARD 0 70#define SFC_CMD(cmd, tmode, awidth, dwidth, pfmt, data_en) \
42#define SFC_MODE_DUAL_IN_DUAL_OUT 1 71 jz_orf(SFC_TRAN_CONF, COMMAND(cmd), CMD_EN(1), \
43#define SFC_MODE_DUAL_IO 2 72 MODE(tmode), ADDR_WIDTH(awidth), DUMMY_BITS(dwidth), \
44#define SFC_MODE_FULL_DUAL_IO 3 73 PHASE_FMT(pfmt), DATA_EN(data_en))
45#define SFC_MODE_QUAD_IN_QUAD_OUT 4
46#define SFC_MODE_QUAD_IO 5
47#define SFC_MODE_FULL_QUAD_IO 6
48 74
49/* Return status codes for sfc_exec() */ 75/* Open/close SFC hardware */
50#define SFC_STATUS_OK 0 76extern void sfc_open(void);
51#define SFC_STATUS_OVERFLOW 1 77extern void sfc_close(void);
52#define SFC_STATUS_UNDERFLOW 2
53#define SFC_STATUS_LOCKUP 3
54 78
55typedef struct sfc_op { 79/* Enable IRQ mode, instead of busy waiting for operations to complete.
56 int command; /* Command number */ 80 * Needs to be called separately after sfc_open(), because the SPL has to
57 int mode; /* SPI transfer mode */ 81 * use busy waiting, but we cannot #ifdef it for the SPL due to limitations
58 int flags; /* Flags for this op */ 82 * of the build system. */
59 int addr_bytes; /* Number of address bytes */ 83extern void sfc_irq_begin(void);
60 int dummy_bits; /* Number of dummy bits (yes: bits, not bytes) */ 84extern void sfc_irq_end(void);
61 uint32_t addr_lo; /* Lower 32 bits of address */
62 uint32_t addr_hi; /* Upper 32 bits of address */
63 int data_bytes; /* Number of data bytes to read/write */
64 void* buffer; /* Data buffer -- MUST be word-aligned */
65} sfc_op;
66 85
67/* One-time driver init for mutexes/etc needed for handling interrupts. 86/* Change the SFC clock frequency */
68 * This can be safely called multiple times; only the first call will 87extern void sfc_set_clock(uint32_t freq);
69 * actually perform the init. 88
70 */ 89/* Set the device configuration register */
71extern void sfc_init(void); 90inline void sfc_set_dev_conf(uint32_t conf)
91{
92 REG_SFC_DEV_CONF = conf;
93}
72 94
73/* Controller mutex -- lock before touching the driver */ 95/* Control the state of the write protect pin */
74extern void sfc_lock(void); 96inline void sfc_set_wp_enable(bool en)
75extern void sfc_unlock(void); 97{
98 jz_writef(SFC_GLB, WP_EN(en ? 1 : 0));
99}
76 100
77/* Open/close the driver. The driver must be open in order to do operations. 101/** \brief Execute a command
78 * Closing the driver shuts off the hardware; the driver can be re-opened at 102 * \param cmd Command encoded by `SFC_CMD` macro.
79 * a later time when it's needed again. 103 * \param addr Address up to 32 bits; pass 0 if the command doesn't need it
104 * \param data Buffer for data transfer commands, must be cache-aligned
105 * \param size Number of data bytes / direction of transfer flag
106 * \returns SFC status code: 0 on success and < 0 on failure.
80 * 107 *
81 * After opening the driver, you must also program a valid device configuration 108 * - Non-data commands must pass `data = NULL` and `size = 0` in order to
82 * and clock rate using sfc_set_dev_conf() and sfc_set_clock(). 109 * get correct results.
110 *
111 * - Data commands must specify a direction of transfer using the high bit
112 * of the `size` argument by OR'ing in `SFC_READ` or `SFC_WRITE`.
83 */ 113 */
84extern void sfc_open(void); 114extern void sfc_exec(uint32_t cmd, uint32_t addr, void* data, uint32_t size);
85extern void sfc_close(void);
86 115
87/* These functions can be called at any time while the driver is open, but 116/* NOTE: the above will need to be changed if we need better performance
88 * must not be called while there is an operation in progress. It's the 117 * The hardware can do multiple commands in a sequence, including polling,
89 * caller's job to ensure the configuration will work with the device and 118 * and emit an interrupt only at the end.
90 * be capable of reading back data correctly.
91 * 119 *
92 * - sfc_set_dev_conf() writes its argument to the SFC_DEV_CONF register. 120 * Also, some chips need more than 4 address bytes even though the block
93 * - sfc_set_wp_enable() sets the state of the write-protect pin (WP). 121 * and page numbers would still fit in 32 bits; the current API cannot
94 * - sfc_set_clock() sets the controller clock frequency (in Hz). 122 * handle this.
95 */ 123 */
96#define sfc_set_dev_conf(dev_conf) \
97 do { REG_SFC_DEV_CONF = (dev_conf); } while(0)
98
99#define sfc_set_wp_enable(en) \
100 jz_writef(SFC_GLB, WP_EN((en) ? 1 : 0))
101
102extern void sfc_set_clock(uint32_t freq);
103 124
104/* Execute an operation. Returns zero on success, nonzero on failure. */ 125#endif /* __SFC_X1000_H__ */
105extern int sfc_exec(const sfc_op* op);