436eb156a66fe8ad9a82282d982141e09948cca7
[fw/openocd] / src / flash / s3c2410_nand.c
1 /* src/flash/s3c2410_nand.c
2  *
3  * S3C2410 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 s3c2410_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
30 int s3c2410_init(struct nand_device_s *device);
31 int s3c2410_read_data(struct nand_device_s *device, void *data);
32 int s3c2410_write_data(struct nand_device_s *device, u16 data);
33 int s3c2410_nand_ready(struct nand_device_s *device, int timeout);
34
35 nand_flash_controller_t s3c2410_nand_controller =
36 {
37         .name                   = "s3c2410",
38         .nand_device_command    = s3c2410_nand_device_command,
39         .register_commands      = s3c24xx_register_commands,
40         .init                   = s3c2410_init,
41         .reset                  = s3c24xx_reset,
42         .command                = s3c24xx_command,
43         .address                = s3c24xx_address,
44         .write_data             = s3c2410_write_data,
45         .read_data              = s3c2410_read_data,
46         .write_page             = s3c24xx_write_page,
47         .read_page              = s3c24xx_read_page,
48         .controller_ready       = s3c24xx_controller_ready,
49         .nand_ready             = s3c2410_nand_ready,
50 };
51
52 int s3c2410_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 = S3C2410_NFCMD;
65         info->addr = S3C2410_NFADDR;
66         info->data = S3C2410_NFDATA;
67         info->nfstat = S3C2410_NFSTAT;
68                 
69         return ERROR_OK;
70 }
71
72 int s3c2410_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                          S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) |
79                          S3C2410_NFCONF_TWRPH0(5) | S3C2410_NFCONF_TWRPH1(3));
80
81         return ERROR_OK;
82 }
83
84 int s3c2410_write_data(struct nand_device_s *device, u16 data)
85 {
86         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
87         target_t *target = s3c24xx_info->target;
88
89         if (target->state != TARGET_HALTED) {
90                 ERROR("target must be halted to use S3C24XX NAND flash controller");
91                 return ERROR_NAND_OPERATION_FAILED;
92         }
93         
94         target_write_u32(target, S3C2410_NFDATA, data);
95         return ERROR_OK;
96 }
97
98 int s3c2410_read_data(struct nand_device_s *device, void *data)
99 {
100         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
101         target_t *target = s3c24xx_info->target;
102         
103         if (target->state != TARGET_HALTED) {
104                 ERROR("target must be halted to use S3C24XX NAND flash controller");
105                 return ERROR_NAND_OPERATION_FAILED;
106         }
107
108         target_read_u8(target, S3C2410_NFDATA, data);   
109         return ERROR_OK;
110 }
111
112 int s3c2410_nand_ready(struct nand_device_s *device, int timeout)
113 {
114         s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
115         target_t *target = s3c24xx_info->target;
116         u8 status;
117
118         if (target->state != TARGET_HALTED) {
119                 ERROR("target must be halted to use S3C24XX NAND flash controller");
120                 return ERROR_NAND_OPERATION_FAILED;
121         }
122         
123         do {
124                 target_read_u8(target, S3C2410_NFSTAT, &status);
125                 
126                 if (status & S3C2410_NFSTAT_BUSY)
127                         return 1;
128
129                 usleep(1000);           
130         } while (timeout-- > 0);
131
132         return 0;
133 }