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