OpenOCD
nuc910.c
Go to the documentation of this file.
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 
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");
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 
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 
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 
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 
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 
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 {
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");
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);
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 */
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 
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 };
Holds the interface to ARM cores.
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
ARM-specific bulk write from buffer to address of 8-bit wide NAND.
Definition: arm_io.c:80
int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
Uses an on-chip algorithm for an ARM device to read from a NAND device and store the data into the ho...
Definition: arm_io.c:190
@ ARM_NAND_NONE
No operation performed.
Definition: arm_io.h:13
void alive_sleep(uint64_t ms)
Definition: log.c:456
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define ERROR_OK
Definition: log.h:164
#define ERROR_NAND_NO_BUFFER
Definition: nand/core.h:222
#define ERROR_NAND_OPERATION_FAILED
Definition: nand/core.h:217
@ NAND_CMD_RESET
Definition: nand/core.h:152
#define ERROR_NAND_OPERATION_NOT_SUPPORTED
Definition: nand/core.h:219
#define ERROR_NAND_DEVICE_INVALID
Definition: nand/core.h:216
static int nuc910_nand_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
Definition: nuc910.c:89
static int nuc910_nand_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
Definition: nuc910.c:113
static int nuc910_nand_command(struct nand_device *nand, uint8_t command)
Definition: nuc910.c:37
static int nuc910_nand_ready(struct nand_device *nand, int timeout)
Definition: nuc910.c:142
static int nuc910_nand_init(struct nand_device *nand)
Definition: nuc910.c:171
static int validate_target_state(struct nand_device *nand)
Definition: nuc910.c:25
NAND_DEVICE_COMMAND_HANDLER(nuc910_nand_device_command)
Definition: nuc910.c:157
static int nuc910_nand_reset(struct nand_device *nand)
Definition: nuc910.c:137
static int nuc910_nand_read(struct nand_device *nand, void *data)
Definition: nuc910.c:63
static int nuc910_nand_write(struct nand_device *nand, uint16_t data)
Definition: nuc910.c:76
static int nuc910_nand_address(struct nand_device *nand, uint8_t address)
Definition: nuc910.c:50
#define NUC910_SMCSR
Definition: nuc910.h:16
#define NUC910_SMTCR
Definition: nuc910.h:17
#define NUC910_SMDATA
Definition: nuc910.h:22
#define NUC910_SMADDR_EOA
Definition: nuc910.h:34
#define NUC910_SMIER
Definition: nuc910.h:18
#define NUC910_SMADDR
Definition: nuc910.h:21
#define NUC910_SMCMD
Definition: nuc910.h:20
#define NUC910_SMISR
Definition: nuc910.h:19
#define NUC910_FMICSR
Definition: nuc910.h:15
#define NUC910_SMISR_RB_
Definition: nuc910.h:42
#define NUC910_FMICSR_SM_EN
Definition: nuc910.h:31
struct target * target
Definition: rtt/rtt.c:26
The arm_nand_data struct is used for defining NAND I/O operations on an ARM core.
Definition: arm_io.h:22
struct target * target
Target is proxy for some ARM core.
Definition: arm_io.h:24
unsigned int chunk_size
The chunk size is the page size or ECC chunk.
Definition: arm_io.h:30
enum arm_nand_op op
Last operation executed using this struct.
Definition: arm_io.h:36
uint32_t data
Where data is read from or written to.
Definition: arm_io.h:33
void * controller_priv
Definition: nand/core.h:51
int page_size
Definition: nand/core.h:56
int bus_width
Definition: nand/core.h:54
struct target * target
Definition: nand/core.h:49
Interface for NAND flash controllers.
Definition: nand/driver.h:23
struct arm_nand_data io
Definition: nuc910.c:22
Definition: target.h:116
enum target_state state
Definition: target.h:157
Definition: psoc6.c:83
int target_write_u8(struct target *target, target_addr_t address, uint8_t value)
Definition: target.c:2683
int target_read_u8(struct target *target, target_addr_t address, uint8_t *value)
Definition: target.c:2598
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2641
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2550
@ TARGET_HALTED
Definition: target.h:56
uint8_t status[4]
Definition: vdebug.c:17