1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2010 by Spencer Oliver *
5 * spen@spen-soft.co.uk *
6 ***************************************************************************/
9 * NAND controller interface for Nuvoton NUC910
19 #include <target/arm.h>
21 struct nuc910_nand_controller
{
22 struct arm_nand_data io
;
25 static int validate_target_state(struct nand_device
*nand
)
27 struct target
*target
= nand
->target
;
29 if (target
->state
!= TARGET_HALTED
) {
30 LOG_ERROR("Target not halted");
31 return ERROR_NAND_OPERATION_FAILED
;
37 static int nuc910_nand_command(struct nand_device
*nand
, uint8_t command
)
39 struct target
*target
= nand
->target
;
42 result
= validate_target_state(nand
);
43 if (result
!= ERROR_OK
)
46 target_write_u8(target
, NUC910_SMCMD
, command
);
50 static int nuc910_nand_address(struct nand_device
*nand
, uint8_t address
)
52 struct target
*target
= nand
->target
;
55 result
= validate_target_state(nand
);
56 if (result
!= ERROR_OK
)
59 target_write_u32(target
, NUC910_SMADDR
, ((address
& 0xff) | NUC910_SMADDR_EOA
));
63 static int nuc910_nand_read(struct nand_device
*nand
, void *data
)
65 struct target
*target
= nand
->target
;
68 result
= validate_target_state(nand
);
69 if (result
!= ERROR_OK
)
72 target_read_u8(target
, NUC910_SMDATA
, data
);
76 static int nuc910_nand_write(struct nand_device
*nand
, uint16_t data
)
78 struct target
*target
= nand
->target
;
81 result
= validate_target_state(nand
);
82 if (result
!= ERROR_OK
)
85 target_write_u8(target
, NUC910_SMDATA
, data
);
89 static int nuc910_nand_read_block_data(struct nand_device
*nand
,
90 uint8_t *data
, int data_size
)
92 struct nuc910_nand_controller
*nuc910_nand
= nand
->controller_priv
;
95 result
= validate_target_state(nand
);
96 if (result
!= ERROR_OK
)
99 nuc910_nand
->io
.chunk_size
= nand
->page_size
;
101 /* try the fast way first */
102 result
= arm_nandread(&nuc910_nand
->io
, data
, data_size
);
103 if (result
!= ERROR_NAND_NO_BUFFER
)
106 /* else do it slowly */
108 nuc910_nand_read(nand
, data
++);
113 static int nuc910_nand_write_block_data(struct nand_device
*nand
,
114 uint8_t *data
, int data_size
)
116 struct nuc910_nand_controller
*nuc910_nand
= nand
->controller_priv
;
119 result
= validate_target_state(nand
);
120 if (result
!= ERROR_OK
)
123 nuc910_nand
->io
.chunk_size
= nand
->page_size
;
125 /* try the fast way first */
126 result
= arm_nandwrite(&nuc910_nand
->io
, data
, data_size
);
127 if (result
!= ERROR_NAND_NO_BUFFER
)
130 /* else do it slowly */
132 nuc910_nand_write(nand
, *data
++);
137 static int nuc910_nand_reset(struct nand_device
*nand
)
139 return nuc910_nand_command(nand
, NAND_CMD_RESET
);
142 static int nuc910_nand_ready(struct nand_device
*nand
, int timeout
)
144 struct target
*target
= nand
->target
;
148 target_read_u32(target
, NUC910_SMISR
, &status
);
149 if (status
& NUC910_SMISR_RB_
)
152 } while (timeout
-- > 0);
157 NAND_DEVICE_COMMAND_HANDLER(nuc910_nand_device_command
)
159 struct nuc910_nand_controller
*nuc910_nand
;
161 nuc910_nand
= calloc(1, sizeof(struct nuc910_nand_controller
));
163 LOG_ERROR("no memory for nand controller");
164 return ERROR_NAND_DEVICE_INVALID
;
167 nand
->controller_priv
= nuc910_nand
;
171 static int nuc910_nand_init(struct nand_device
*nand
)
173 struct nuc910_nand_controller
*nuc910_nand
= nand
->controller_priv
;
174 struct target
*target
= nand
->target
;
175 int bus_width
= nand
->bus_width
? nand
->bus_width
: 8;
178 result
= validate_target_state(nand
);
179 if (result
!= ERROR_OK
)
182 /* nuc910 only supports 8bit */
183 if (bus_width
!= 8) {
184 LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width
);
185 return ERROR_NAND_OPERATION_NOT_SUPPORTED
;
188 /* inform calling code about selected bus width */
189 nand
->bus_width
= bus_width
;
191 nuc910_nand
->io
.target
= target
;
192 nuc910_nand
->io
.data
= NUC910_SMDATA
;
193 nuc910_nand
->io
.op
= ARM_NAND_NONE
;
195 /* configure nand controller */
196 target_write_u32(target
, NUC910_FMICSR
, NUC910_FMICSR_SM_EN
);
197 target_write_u32(target
, NUC910_SMCSR
, 0x010000a8); /* 2048 page size */
198 target_write_u32(target
, NUC910_SMTCR
, 0x00010204);
199 target_write_u32(target
, NUC910_SMIER
, 0x00000000);
204 struct nand_flash_controller nuc910_nand_controller
= {
206 .command
= nuc910_nand_command
,
207 .address
= nuc910_nand_address
,
208 .read_data
= nuc910_nand_read
,
209 .write_data
= nuc910_nand_write
,
210 .write_block_data
= nuc910_nand_write_block_data
,
211 .read_block_data
= nuc910_nand_read_block_data
,
212 .nand_ready
= nuc910_nand_ready
,
213 .reset
= nuc910_nand_reset
,
214 .nand_device_command
= nuc910_nand_device_command
,
215 .init
= nuc910_nand_init
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)