jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nand / nuc910.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2010 by Spencer Oliver *
5 * spen@spen-soft.co.uk *
6 ***************************************************************************/
7
8 /*
9 * NAND controller interface for Nuvoton NUC910
10 */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include "imp.h"
17 #include "nuc910.h"
18 #include "arm_io.h"
19 #include <target/arm.h>
20
21 struct nuc910_nand_controller {
22 struct arm_nand_data io;
23 };
24
25 static int validate_target_state(struct nand_device *nand)
26 {
27 struct target *target = nand->target;
28
29 if (target->state != TARGET_HALTED) {
30 LOG_ERROR("Target not halted");
31 return ERROR_NAND_OPERATION_FAILED;
32 }
33
34 return ERROR_OK;
35 }
36
37 static int nuc910_nand_command(struct nand_device *nand, uint8_t command)
38 {
39 struct target *target = nand->target;
40 int result;
41
42 result = validate_target_state(nand);
43 if (result != ERROR_OK)
44 return result;
45
46 target_write_u8(target, NUC910_SMCMD, command);
47 return ERROR_OK;
48 }
49
50 static int nuc910_nand_address(struct nand_device *nand, uint8_t address)
51 {
52 struct target *target = nand->target;
53 int result;
54
55 result = validate_target_state(nand);
56 if (result != ERROR_OK)
57 return result;
58
59 target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA));
60 return ERROR_OK;
61 }
62
63 static int nuc910_nand_read(struct nand_device *nand, void *data)
64 {
65 struct target *target = nand->target;
66 int result;
67
68 result = validate_target_state(nand);
69 if (result != ERROR_OK)
70 return result;
71
72 target_read_u8(target, NUC910_SMDATA, data);
73 return ERROR_OK;
74 }
75
76 static int nuc910_nand_write(struct nand_device *nand, uint16_t data)
77 {
78 struct target *target = nand->target;
79 int result;
80
81 result = validate_target_state(nand);
82 if (result != ERROR_OK)
83 return result;
84
85 target_write_u8(target, NUC910_SMDATA, data);
86 return ERROR_OK;
87 }
88
89 static int nuc910_nand_read_block_data(struct nand_device *nand,
90 uint8_t *data, int data_size)
91 {
92 struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
93 int result;
94
95 result = validate_target_state(nand);
96 if (result != ERROR_OK)
97 return result;
98
99 nuc910_nand->io.chunk_size = nand->page_size;
100
101 /* try the fast way first */
102 result = arm_nandread(&nuc910_nand->io, data, data_size);
103 if (result != ERROR_NAND_NO_BUFFER)
104 return result;
105
106 /* else do it slowly */
107 while (data_size--)
108 nuc910_nand_read(nand, data++);
109
110 return ERROR_OK;
111 }
112
113 static int nuc910_nand_write_block_data(struct nand_device *nand,
114 uint8_t *data, int data_size)
115 {
116 struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
117 int result;
118
119 result = validate_target_state(nand);
120 if (result != ERROR_OK)
121 return result;
122
123 nuc910_nand->io.chunk_size = nand->page_size;
124
125 /* try the fast way first */
126 result = arm_nandwrite(&nuc910_nand->io, data, data_size);
127 if (result != ERROR_NAND_NO_BUFFER)
128 return result;
129
130 /* else do it slowly */
131 while (data_size--)
132 nuc910_nand_write(nand, *data++);
133
134 return ERROR_OK;
135 }
136
137 static int nuc910_nand_reset(struct nand_device *nand)
138 {
139 return nuc910_nand_command(nand, NAND_CMD_RESET);
140 }
141
142 static int nuc910_nand_ready(struct nand_device *nand, int timeout)
143 {
144 struct target *target = nand->target;
145 uint32_t status;
146
147 do {
148 target_read_u32(target, NUC910_SMISR, &status);
149 if (status & NUC910_SMISR_RB_)
150 return 1;
151 alive_sleep(1);
152 } while (timeout-- > 0);
153
154 return 0;
155 }
156
157 NAND_DEVICE_COMMAND_HANDLER(nuc910_nand_device_command)
158 {
159 struct nuc910_nand_controller *nuc910_nand;
160
161 nuc910_nand = calloc(1, sizeof(struct nuc910_nand_controller));
162 if (!nuc910_nand) {
163 LOG_ERROR("no memory for nand controller");
164 return ERROR_NAND_DEVICE_INVALID;
165 }
166
167 nand->controller_priv = nuc910_nand;
168 return ERROR_OK;
169 }
170
171 static int nuc910_nand_init(struct nand_device *nand)
172 {
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;
176 int result;
177
178 result = validate_target_state(nand);
179 if (result != ERROR_OK)
180 return result;
181
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;
186 }
187
188 /* inform calling code about selected bus width */
189 nand->bus_width = bus_width;
190
191 nuc910_nand->io.target = target;
192 nuc910_nand->io.data = NUC910_SMDATA;
193 nuc910_nand->io.op = ARM_NAND_NONE;
194
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);
200
201 return ERROR_OK;
202 }
203
204 struct nand_flash_controller nuc910_nand_controller = {
205 .name = "nuc910",
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,
216 };

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)