openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nand / s3c2440.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
5  *   ben@fluff.org                                                         *
6  ***************************************************************************/
7
8 /*
9  * S3C2440 OpenOCD NAND Flash controller support.
10  *
11  * Many thanks to Simtec Electronics for sponsoring this work.
12  */
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include "s3c24xx.h"
19
20 NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
21 {
22         struct s3c24xx_nand_controller *info;
23         CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
24
25         /* fill in the address fields for the core device */
26         info->cmd = S3C2440_NFCMD;
27         info->addr = S3C2440_NFADDR;
28         info->data = S3C2440_NFDATA;
29         info->nfstat = S3C2440_NFSTAT;
30
31         return ERROR_OK;
32 }
33
34 static int s3c2440_init(struct nand_device *nand)
35 {
36         struct target *target = nand->target;
37
38         target_write_u32(target, S3C2410_NFCONF,
39                          S3C2440_NFCONF_TACLS(3) |
40                          S3C2440_NFCONF_TWRPH0(7) |
41                          S3C2440_NFCONF_TWRPH1(7));
42
43         target_write_u32(target, S3C2440_NFCONT,
44                          S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
45
46         return ERROR_OK;
47 }
48
49 int s3c2440_nand_ready(struct nand_device *nand, int timeout)
50 {
51         struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
52         struct target *target = nand->target;
53         uint8_t status;
54
55         if (target->state != TARGET_HALTED) {
56                 LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
57                 return ERROR_NAND_OPERATION_FAILED;
58         }
59
60         do {
61                 target_read_u8(target, s3c24xx_info->nfstat, &status);
62
63                 if (status & S3C2440_NFSTAT_READY)
64                         return 1;
65
66                 alive_sleep(1);
67         } while (timeout-- > 0);
68
69
70         return 0;
71 }
72
73 /* use the fact we can read/write 4 bytes in one go via a single 32bit op */
74
75 int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
76 {
77         struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
78         struct target *target = nand->target;
79         uint32_t nfdata = s3c24xx_info->data;
80         uint32_t tmp;
81
82         LOG_INFO("%s: reading data: %p, %p, %d", __func__, nand, data, data_size);
83
84         if (target->state != TARGET_HALTED) {
85                 LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
86                 return ERROR_NAND_OPERATION_FAILED;
87         }
88
89         while (data_size >= 4) {
90                 target_read_u32(target, nfdata, &tmp);
91
92                 data[0] = tmp;
93                 data[1] = tmp >> 8;
94                 data[2] = tmp >> 16;
95                 data[3] = tmp >> 24;
96
97                 data_size -= 4;
98                 data += 4;
99         }
100
101         while (data_size > 0) {
102                 target_read_u8(target, nfdata, data);
103
104                 data_size -= 1;
105                 data += 1;
106         }
107
108         return ERROR_OK;
109 }
110
111 int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
112 {
113         struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
114         struct target *target = nand->target;
115         uint32_t nfdata = s3c24xx_info->data;
116         uint32_t tmp;
117
118         if (target->state != TARGET_HALTED) {
119                 LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
120                 return ERROR_NAND_OPERATION_FAILED;
121         }
122
123         while (data_size >= 4) {
124                 tmp = le_to_h_u32(data);
125                 target_write_u32(target, nfdata, tmp);
126
127                 data_size -= 4;
128                 data += 4;
129         }
130
131         while (data_size > 0) {
132                 target_write_u8(target, nfdata, *data);
133
134                 data_size -= 1;
135                 data += 1;
136         }
137
138         return ERROR_OK;
139 }
140
141 struct nand_flash_controller s3c2440_nand_controller = {
142         .name = "s3c2440",
143         .nand_device_command = &s3c2440_nand_device_command,
144         .init = &s3c2440_init,
145         .reset = &s3c24xx_reset,
146         .command = &s3c24xx_command,
147         .address = &s3c24xx_address,
148         .write_data = &s3c24xx_write_data,
149         .read_data = &s3c24xx_read_data,
150         .write_page = s3c24xx_write_page,
151         .read_page = s3c24xx_read_page,
152         .write_block_data = &s3c2440_write_block_data,
153         .read_block_data = &s3c2440_read_block_data,
154         .nand_ready = &s3c2440_nand_ready,
155 };