]> git.sur5r.net Git - openocd/blob - src/flash/s3c2440_nand.c
a6b9b04d7dbd540771db984844d279c065383738
[openocd] / src / flash / s3c2440_nand.c
1 /* src/flash/s3c2440_nand.c
2  *
3  * S3C2440 OpenOCD NAND Flash controller support.
4  *
5  * Copyright 2007,2008 Ben Dooks <ben@fluff.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * Many thanks to Simtec Electronics for sponsoring this work.
13  */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #include "replacements.h"
20 #include "log.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "nand.h"
26 #include "s3c24xx_nand.h"
27 #include "target.h"
28
29 int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
30 int s3c2440_init(struct nand_device_s *device);
31 int s3c2440_nand_ready(struct nand_device_s *device, int timeout);
32
33 nand_flash_controller_t s3c2440_nand_controller =
34 {
35         .name                   = "s3c2440",
36         .nand_device_command    = s3c2440_nand_device_command,
37         .register_commands      = s3c24xx_register_commands,
38         .init                   = s3c2440_init,
39         .reset                  = s3c24xx_reset,
40         .command                = s3c24xx_command,
41         .address                = s3c24xx_address,
42         .write_data             = s3c24xx_write_data,
43         .read_data              = s3c24xx_read_data,
44         .write_page             = s3c24xx_write_page,
45         .read_page              = s3c24xx_read_page,
46         .write_block_data       = s3c2440_write_block_data,
47         .read_block_data        = s3c2440_read_block_data,
48         .controller_ready       = s3c24xx_controller_ready,
49         .nand_ready             = s3c2440_nand_ready,
50 };
51
52 int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
53                                 char **args, int argc,
54                                 struct nand_device_s *device)
55 {
56         s3c24xx_nand_controller_t *info;
57         
58         info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
59         if (info == NULL) {
60                 return ERROR_NAND_DEVICE_INVALID;
61         }
62
63         /* fill in the address fields for the core device */
64         info->cmd = S3C2440_NFCMD;
65         info->addr = S3C2440_NFADDR;
66         info->data = S3C2440_NFDATA;
67         info->nfstat = S3C2440_NFSTAT;
68                 
69         return ERROR_OK;
70 }
71
72 int s3c2440_init(struct nand_device_s *device)
73 {
74         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
75         target_t *target = s3c24xx_info->target;
76
77         target_write_u32(target, S3C2410_NFCONF,
78                          S3C2440_NFCONF_TACLS(3) |
79                          S3C2440_NFCONF_TWRPH0(7) |
80                          S3C2440_NFCONF_TWRPH1(7));
81
82         target_write_u32(target, S3C2440_NFCONT,
83                          S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
84
85         return ERROR_OK;
86 }
87
88 int s3c2440_nand_ready(struct nand_device_s *device, int timeout)
89 {
90         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
91         target_t *target = s3c24xx_info->target;
92         u8 status;
93
94         if (target->state != TARGET_HALTED) {
95                 ERROR("target must be halted to use S3C24XX NAND flash controller");
96                 return ERROR_NAND_OPERATION_FAILED;
97         }
98         
99         do {            
100                 target_read_u8(target, s3c24xx_info->nfstat, &status);
101                 
102                 if (status & S3C2440_NFSTAT_READY)
103                         return 1;
104
105                 usleep(1000);
106         } while (timeout-- > 0);
107
108
109         return 0;
110 }
111
112 /* use the fact we can read/write 4 bytes in one go via a single 32bit op */
113
114 int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size)
115 {
116         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
117         target_t *target = s3c24xx_info->target;
118         u32 nfdata = s3c24xx_info->data;
119         u32 tmp;
120
121         INFO("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size);
122
123         if (target->state != TARGET_HALTED) {
124                 ERROR("target must be halted to use S3C24XX NAND flash controller");
125                 return ERROR_NAND_OPERATION_FAILED;
126         }
127
128         while (data_size >= 4) {          
129                 target_read_u32(target, nfdata, &tmp);
130
131                 data[0] = tmp;
132                 data[1] = tmp >> 8;
133                 data[2] = tmp >> 16;
134                 data[3] = tmp >> 24;
135
136                 data_size -= 4;
137                 data += 4;
138         }
139
140         while (data_size > 0) {
141                 target_read_u8(target, nfdata, data);
142
143                 data_size -= 1;
144                 data += 1;
145         }
146
147         return ERROR_OK;
148 }
149
150 int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size)
151 {
152         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
153         target_t *target = s3c24xx_info->target;
154         u32 nfdata = s3c24xx_info->data;
155         u32 tmp;
156
157         if (target->state != TARGET_HALTED) {
158                 ERROR("target must be halted to use S3C24XX NAND flash controller");
159                 return ERROR_NAND_OPERATION_FAILED;
160         }
161
162         while (data_size >= 4) {          
163                 tmp = le_to_h_u32(data);
164                 target_write_u32(target, nfdata, tmp);
165
166                 data_size -= 4;
167                 data += 4;
168         }
169
170         while (data_size > 0) {
171                 target_write_u8(target, nfdata, *data);
172
173                 data_size -= 1;
174                 data += 1;
175         }
176
177         return ERROR_OK;
178 }