s3c2440.c 4.81 KB
Newer Older
oharboe's avatar
oharboe committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***************************************************************************
 *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
 *   ben@fluff.org                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

/*
drath's avatar
drath committed
22
23
24
25
26
27
28
29
30
 * S3C2440 OpenOCD NAND Flash controller support.
 *
 * Many thanks to Simtec Electronics for sponsoring this work.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

31
#include "s3c24xx.h"
32

drath's avatar
drath committed
33

34
NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
drath's avatar
drath committed
35
{
36
	struct s3c24xx_nand_controller *info;
37
	CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
drath's avatar
drath committed
38
39
40
41
42
43

	/* fill in the address fields for the core device */
	info->cmd = S3C2440_NFCMD;
	info->addr = S3C2440_NFADDR;
	info->data = S3C2440_NFDATA;
	info->nfstat = S3C2440_NFSTAT;
44

drath's avatar
drath committed
45
46
47
	return ERROR_OK;
}

48
static int s3c2440_init(struct nand_device *nand)
drath's avatar
drath committed
49
{
50
	struct target *target = nand->target;
drath's avatar
drath committed
51
52
53
54
55
56
57
58
59
60
61
62

	target_write_u32(target, S3C2410_NFCONF,
			 S3C2440_NFCONF_TACLS(3) |
			 S3C2440_NFCONF_TWRPH0(7) |
			 S3C2440_NFCONF_TWRPH1(7));

	target_write_u32(target, S3C2440_NFCONT,
			 S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);

	return ERROR_OK;
}

63
int s3c2440_nand_ready(struct nand_device *nand, int timeout)
drath's avatar
drath committed
64
{
65
	struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
66
	struct target *target = nand->target;
67
	uint8_t status;
drath's avatar
drath committed
68
69

	if (target->state != TARGET_HALTED) {
70
		LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
drath's avatar
drath committed
71
72
		return ERROR_NAND_OPERATION_FAILED;
	}
73
74

	do {
drath's avatar
drath committed
75
		target_read_u8(target, s3c24xx_info->nfstat, &status);
76

drath's avatar
drath committed
77
78
79
		if (status & S3C2440_NFSTAT_READY)
			return 1;

80
		alive_sleep(1);
drath's avatar
drath committed
81
82
83
84
85
86
87
88
	} while (timeout-- > 0);


	return 0;
}

/* use the fact we can read/write 4 bytes in one go via a single 32bit op */

89
int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
drath's avatar
drath committed
90
{
91
	struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
92
	struct target *target = nand->target;
93
94
	uint32_t nfdata = s3c24xx_info->data;
	uint32_t tmp;
drath's avatar
drath committed
95

Eric Wetzel's avatar
Eric Wetzel committed
96
	LOG_INFO("%s: reading data: %p, %p, %d", __func__, nand, data, data_size);
drath's avatar
drath committed
97
98

	if (target->state != TARGET_HALTED) {
99
		LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
drath's avatar
drath committed
100
101
102
		return ERROR_NAND_OPERATION_FAILED;
	}

103
	while (data_size >= 4) {
drath's avatar
drath committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
		target_read_u32(target, nfdata, &tmp);

		data[0] = tmp;
		data[1] = tmp >> 8;
		data[2] = tmp >> 16;
		data[3] = tmp >> 24;

		data_size -= 4;
		data += 4;
	}

	while (data_size > 0) {
		target_read_u8(target, nfdata, data);

		data_size -= 1;
		data += 1;
	}

	return ERROR_OK;
}

125
int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
drath's avatar
drath committed
126
{
127
	struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
128
	struct target *target = nand->target;
129
130
	uint32_t nfdata = s3c24xx_info->data;
	uint32_t tmp;
drath's avatar
drath committed
131
132

	if (target->state != TARGET_HALTED) {
133
		LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
drath's avatar
drath committed
134
135
136
		return ERROR_NAND_OPERATION_FAILED;
	}

137
	while (data_size >= 4) {
drath's avatar
drath committed
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
		tmp = le_to_h_u32(data);
		target_write_u32(target, nfdata, tmp);

		data_size -= 4;
		data += 4;
	}

	while (data_size > 0) {
		target_write_u8(target, nfdata, *data);

		data_size -= 1;
		data += 1;
	}

	return ERROR_OK;
}
154

155
struct nand_flash_controller s3c2440_nand_controller = {
156
157
158
159
160
161
162
163
164
165
166
167
168
169
		.name = "s3c2440",
		.nand_device_command = &s3c2440_nand_device_command,
		.init = &s3c2440_init,
		.reset = &s3c24xx_reset,
		.command = &s3c24xx_command,
		.address = &s3c24xx_address,
		.write_data = &s3c24xx_write_data,
		.read_data = &s3c24xx_read_data,
		.write_page = s3c24xx_write_page,
		.read_page = s3c24xx_read_page,
		.write_block_data = &s3c2440_write_block_data,
		.read_block_data = &s3c2440_read_block_data,
		.nand_ready = &s3c2440_nand_ready,
	};