Tue Oct 4 15:32:03 2016 UTC ()
Remove a comment-out-ed and no-need line.


(kiyohara)
diff -r1.5 -r1.6 src/sys/arch/arm/omap/omap2_nand.c

cvs diff -r1.5 -r1.6 src/sys/arch/arm/omap/Attic/omap2_nand.c (switch to unified diff)

--- src/sys/arch/arm/omap/Attic/omap2_nand.c 2012/10/27 17:17:40 1.5
+++ src/sys/arch/arm/omap/Attic/omap2_nand.c 2016/10/04 15:32:02 1.6
@@ -1,514 +1,513 @@ @@ -1,514 +1,513 @@
1/* $NetBSD: omap2_nand.c,v 1.5 2012/10/27 17:17:40 chs Exp $ */ 1/* $NetBSD: omap2_nand.c,v 1.6 2016/10/04 15:32:02 kiyohara Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010 Department of Software Engineering, 4 * Copyright (c) 2010 Department of Software Engineering,
5 * University of Szeged, Hungary 5 * University of Szeged, Hungary
6 * Copyright (c) 2010 Adam Hoka <ahoka@NetBSD.org> 6 * Copyright (c) 2010 Adam Hoka <ahoka@NetBSD.org>
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * This code is derived from software contributed to The NetBSD Foundation 9 * This code is derived from software contributed to The NetBSD Foundation
10 * by the Department of Software Engineering, University of Szeged, Hungary 10 * by the Department of Software Engineering, University of Szeged, Hungary
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
15 * 1. Redistributions of source code must retain the above copyright 15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer. 16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright 17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the 18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution. 19 * documentation and/or other materials provided with the distribution.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE. 31 * SUCH DAMAGE.
32 */ 32 */
33 33
34/* Device driver for the NAND controller found in Texas Instruments OMAP2 34/* Device driver for the NAND controller found in Texas Instruments OMAP2
35 * and later SOCs. 35 * and later SOCs.
36 */ 36 */
37 37
38#include <sys/cdefs.h> 38#include <sys/cdefs.h>
39__KERNEL_RCSID(0, "$NetBSD: omap2_nand.c,v 1.5 2012/10/27 17:17:40 chs Exp $"); 39__KERNEL_RCSID(0, "$NetBSD: omap2_nand.c,v 1.6 2016/10/04 15:32:02 kiyohara Exp $");
40 40
41#include "opt_omap.h" 41#include "opt_omap.h"
42#include "opt_flash.h" 42#include "opt_flash.h"
43 43
44/* TODO move to opt_* */ 44/* TODO move to opt_* */
45#undef OMAP2_NAND_HARDWARE_ECC 45#undef OMAP2_NAND_HARDWARE_ECC
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/systm.h> 48#include <sys/systm.h>
49#include <sys/cdefs.h> 49#include <sys/cdefs.h>
50#include <sys/device.h> 50#include <sys/device.h>
51 51
52#include <sys/bus.h> 52#include <sys/bus.h>
53 53
54#include <arch/arm/omap/omap2_gpmcvar.h> 54#include <arch/arm/omap/omap2_gpmcvar.h>
55#include <arch/arm/omap/omap2_gpmcreg.h> 55#include <arch/arm/omap/omap2_gpmcreg.h>
56 56
57#include <dev/nand/nand.h> 57#include <dev/nand/nand.h>
58#include <dev/nand/onfi.h> 58#include <dev/nand/onfi.h>
59 59
60/* GPMC_STATUS */ 60/* GPMC_STATUS */
61#define WAIT0 __BIT(8) /* active low */ 61#define WAIT0 __BIT(8) /* active low */
62 62
63/* GPMC_ECC_CONTROL */ 63/* GPMC_ECC_CONTROL */
64#define ECCCLEAR __BIT(8) 64#define ECCCLEAR __BIT(8)
65#define ECCPOINTER __BITS(3,0) 65#define ECCPOINTER __BITS(3,0)
66 66
67/* GPMC_ECC_CONFIG */ 67/* GPMC_ECC_CONFIG */
68#define ECCALGORITHM __BIT(16) 68#define ECCALGORITHM __BIT(16)
69#define ECCCS __BITS(3,1) 69#define ECCCS __BITS(3,1)
70#define ECC16B __BIT(7) 70#define ECC16B __BIT(7)
71#define ECCENABLE __BIT(0) 71#define ECCENABLE __BIT(0)
72/* GPMC_ECC_SIZE_CONFIG */ 72/* GPMC_ECC_SIZE_CONFIG */
73#define ECCSIZE1 __BITS(29,22) 73#define ECCSIZE1 __BITS(29,22)
74 74
75/* GPMC_CONFIG1_i */ 75/* GPMC_CONFIG1_i */
76#define DEVICETYPE __BITS(11,10) 76#define DEVICETYPE __BITS(11,10)
77#define DEVICESIZE __BITS(13,12) 77#define DEVICESIZE __BITS(13,12)
78 78
79#define MASKEDINT(mask, integer) ((integer) << (ffs(mask) - 1) & mask) 79#define MASKEDINT(mask, integer) ((integer) << (ffs(mask) - 1) & mask)
80 80
81/* NAND status register */ 81/* NAND status register */
82#define NAND_WP_BIT __BIT(4) 82#define NAND_WP_BIT __BIT(4)
83 83
84static int omap2_nand_match(device_t, cfdata_t, void *); 84static int omap2_nand_match(device_t, cfdata_t, void *);
85static void omap2_nand_attach(device_t, device_t, void *); 85static void omap2_nand_attach(device_t, device_t, void *);
86static int omap2_nand_detach(device_t, int); 86static int omap2_nand_detach(device_t, int);
87 87
88void omap2_nand_command(device_t self, uint8_t command); 88void omap2_nand_command(device_t self, uint8_t command);
89void omap2_nand_address(device_t self, uint8_t address); 89void omap2_nand_address(device_t self, uint8_t address);
90void omap2_nand_busy(device_t self); 90void omap2_nand_busy(device_t self);
91void omap2_nand_read_1(device_t self, uint8_t *data); 91void omap2_nand_read_1(device_t self, uint8_t *data);
92void omap2_nand_write_1(device_t self, uint8_t data); 92void omap2_nand_write_1(device_t self, uint8_t data);
93void omap2_nand_read_2(device_t self, uint16_t *data); 93void omap2_nand_read_2(device_t self, uint16_t *data);
94void omap2_nand_write_2(device_t self, uint16_t data); 94void omap2_nand_write_2(device_t self, uint16_t data);
95bool omap2_nand_isbusy(device_t self); 95bool omap2_nand_isbusy(device_t self);
96void omap2_nand_read_buf_1(device_t self, void *buf, size_t len); 96void omap2_nand_read_buf_1(device_t self, void *buf, size_t len);
97void omap2_nand_read_buf_2(device_t self, void *buf, size_t len); 97void omap2_nand_read_buf_2(device_t self, void *buf, size_t len);
98void omap2_nand_write_buf_1(device_t self, const void *buf, size_t len); 98void omap2_nand_write_buf_1(device_t self, const void *buf, size_t len);
99void omap2_nand_write_buf_2(device_t self, const void *buf, size_t len); 99void omap2_nand_write_buf_2(device_t self, const void *buf, size_t len);
100 100
101int omap2_nand_ecc_init(device_t self); 101int omap2_nand_ecc_init(device_t self);
102int omap2_nand_ecc_prepare(device_t self, int mode); 102int omap2_nand_ecc_prepare(device_t self, int mode);
103int omap2_nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *ecc); 103int omap2_nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *ecc);
104int omap2_nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldecc, 104int omap2_nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldecc,
105 const uint8_t *calcecc); 105 const uint8_t *calcecc);
106 106
107struct omap2_nand_softc { 107struct omap2_nand_softc {
108 device_t sc_dev; 108 device_t sc_dev;
109 device_t sc_nanddev; 109 device_t sc_nanddev;
110 struct gpmc_softc *sc_gpmcsc; 110 struct gpmc_softc *sc_gpmcsc;
111 111
112 int sc_cs; 112 int sc_cs;
113 int sc_buswidth; /* 0: 8bit, 1: 16bit */ 113 int sc_buswidth; /* 0: 8bit, 1: 16bit */
114 114
115 struct nand_interface sc_nand_if; 115 struct nand_interface sc_nand_if;
116 116
117 bus_space_handle_t sc_ioh; 117 bus_space_handle_t sc_ioh;
118 bus_space_tag_t sc_iot; 118 bus_space_tag_t sc_iot;
119 119
120 bus_size_t sc_cmd_reg; 120 bus_size_t sc_cmd_reg;
121 bus_size_t sc_addr_reg; 121 bus_size_t sc_addr_reg;
122 bus_size_t sc_data_reg; 122 bus_size_t sc_data_reg;
123}; 123};
124 124
125CFATTACH_DECL_NEW(omapnand, sizeof(struct omap2_nand_softc), omap2_nand_match, 125CFATTACH_DECL_NEW(omapnand, sizeof(struct omap2_nand_softc), omap2_nand_match,
126 omap2_nand_attach, omap2_nand_detach, NULL); 126 omap2_nand_attach, omap2_nand_detach, NULL);
127 127
128void 128void
129omap2_nand_command(device_t self, uint8_t command) 129omap2_nand_command(device_t self, uint8_t command)
130{ 130{
131 struct omap2_nand_softc *sc = device_private(self); 131 struct omap2_nand_softc *sc = device_private(self);
132 132
133 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_cmd_reg, command); 133 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_cmd_reg, command);
134}; 134};
135 135
136void 136void
137omap2_nand_address(device_t self, uint8_t address) 137omap2_nand_address(device_t self, uint8_t address)
138{ 138{
139 struct omap2_nand_softc *sc = device_private(self); 139 struct omap2_nand_softc *sc = device_private(self);
140 140
141 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_addr_reg, address); 141 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_addr_reg, address);
142}; 142};
143 143
144bool 144bool
145omap2_nand_isbusy(device_t self) 145omap2_nand_isbusy(device_t self)
146{ 146{
147 struct omap2_nand_softc *sc = device_private(self); 147 struct omap2_nand_softc *sc = device_private(self);
148 uint8_t status; 148 uint8_t status;
149 149
150 DELAY(1); /* just to be sure we are not early */ 150 DELAY(1); /* just to be sure we are not early */
151 151
152 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 152 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
153 sc->sc_cmd_reg, ONFI_READ_STATUS); 153 sc->sc_cmd_reg, ONFI_READ_STATUS);
154 154
155 DELAY(1); 155 DELAY(1);
156 156
157 status = bus_space_read_1(sc->sc_iot, 157 status = bus_space_read_1(sc->sc_iot,
158 sc->sc_ioh, sc->sc_data_reg); 158 sc->sc_ioh, sc->sc_data_reg);
159 159
160 return !(status & ONFI_STATUS_RDY); 160 return !(status & ONFI_STATUS_RDY);
161}; 161};
162 162
163static int 163static int
164omap2_nand_match(device_t parent, cfdata_t match, void *aux) 164omap2_nand_match(device_t parent, cfdata_t match, void *aux)
165{ 165{
166 struct gpmc_attach_args *gpmc = aux; 166 struct gpmc_attach_args *gpmc = aux;
167 bus_space_tag_t iot; 167 bus_space_tag_t iot;
168 bus_space_handle_t ioh; 168 bus_space_handle_t ioh;
169 bus_size_t cs_offset; 169 bus_size_t cs_offset;
170 uint32_t result; 170 uint32_t result;
171 int ret = 0; 171 int ret = 0;
172 172
173 iot = gpmc->gpmc_iot; 173 iot = gpmc->gpmc_iot;
174 174
175 cs_offset = GPMC_CS_CONFIG_BASE(gpmc->gpmc_cs); 175 cs_offset = GPMC_CS_CONFIG_BASE(gpmc->gpmc_cs);
176 176
177 /* map i/o space */ 177 /* map i/o space */
178 if (bus_space_map(iot, cs_offset, GPMC_CS_SIZE, 0, &ioh) != 0) { 178 if (bus_space_map(iot, cs_offset, GPMC_CS_SIZE, 0, &ioh) != 0) {
179 aprint_error("omap2_nand_match: can't map i/o space"); 179 aprint_error("omap2_nand_match: can't map i/o space");
180 return 1; 180 return 1;
181 } 181 }
182 182
183 /* read GPMC_CONFIG1_i */ 183 /* read GPMC_CONFIG1_i */
184 result = bus_space_read_4(iot, ioh, GPMC_CONFIG1_i); 184 result = bus_space_read_4(iot, ioh, GPMC_CONFIG1_i);
185 185
186 /* check if memory device is NAND type */ 186 /* check if memory device is NAND type */
187 if ((result & DEVICETYPE) == MASKEDINT(DEVICETYPE, 0x02)) { 187 if ((result & DEVICETYPE) == MASKEDINT(DEVICETYPE, 0x02)) {
188 /* we got NAND, report positive match */ 188 /* we got NAND, report positive match */
189 ret = 1; 189 ret = 1;
190 } 190 }
191 191
192 bus_space_unmap(iot, ioh, GPMC_CS_SIZE); 192 bus_space_unmap(iot, ioh, GPMC_CS_SIZE);
193 193
194 return ret; 194 return ret;
195} 195}
196 196
197static void 197static void
198omap2_nand_attach(device_t parent, device_t self, void *aux) 198omap2_nand_attach(device_t parent, device_t self, void *aux)
199{ 199{
200 struct omap2_nand_softc *sc = device_private(self); 200 struct omap2_nand_softc *sc = device_private(self);
201 sc->sc_gpmcsc = device_private(parent); 201 sc->sc_gpmcsc = device_private(parent);
202 struct gpmc_attach_args *gpmc = aux; 202 struct gpmc_attach_args *gpmc = aux;
203 bus_size_t cs_offset; 203 bus_size_t cs_offset;
204 uint32_t val; 204 uint32_t val;
205 205
206 aprint_normal("\n"); 206 aprint_normal("\n");
207 207
208 sc->sc_iot = gpmc->gpmc_iot; 208 sc->sc_iot = gpmc->gpmc_iot;
209 sc->sc_dev = self; 209 sc->sc_dev = self;
210 sc->sc_cs = gpmc->gpmc_cs; 210 sc->sc_cs = gpmc->gpmc_cs;
211 211
212// cs_offset = GPMC_BASE + GPMC_CONFIG1_0 + sc->sc_cs * GPMC_CS_SIZE; 
213 cs_offset = GPMC_CS_CONFIG_BASE(sc->sc_cs); 212 cs_offset = GPMC_CS_CONFIG_BASE(sc->sc_cs);
214 213
215 /* map i/o space */ 214 /* map i/o space */
216 if (bus_space_map(sc->sc_iot, cs_offset, GPMC_CS_SIZE, 0, 215 if (bus_space_map(sc->sc_iot, cs_offset, GPMC_CS_SIZE, 0,
217 &sc->sc_ioh) != 0) { 216 &sc->sc_ioh) != 0) {
218 aprint_error(": omap2_nand_attach: can't map i/o space"); 217 aprint_error(": omap2_nand_attach: can't map i/o space");
219 return; 218 return;
220 } 219 }
221 220
222 sc->sc_cmd_reg = GPMC_NAND_COMMAND_0 - GPMC_CONFIG1_0; 221 sc->sc_cmd_reg = GPMC_NAND_COMMAND_0 - GPMC_CONFIG1_0;
223 sc->sc_addr_reg = GPMC_NAND_ADDRESS_0 - GPMC_CONFIG1_0; 222 sc->sc_addr_reg = GPMC_NAND_ADDRESS_0 - GPMC_CONFIG1_0;
224 sc->sc_data_reg = GPMC_NAND_DATA_0 - GPMC_CONFIG1_0; 223 sc->sc_data_reg = GPMC_NAND_DATA_0 - GPMC_CONFIG1_0;
225 224
226 /* turn off write protection if enabled */ 225 /* turn off write protection if enabled */
227 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_CONFIG); 226 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_CONFIG);
228 val |= NAND_WP_BIT; 227 val |= NAND_WP_BIT;
229 gpmc_register_write(sc->sc_gpmcsc, GPMC_CONFIG, val); 228 gpmc_register_write(sc->sc_gpmcsc, GPMC_CONFIG, val);
230 229
231 /* 230 /*
232 * do the reset dance for NAND 231 * do the reset dance for NAND
233 */ 232 */
234 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 233 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
235 sc->sc_cmd_reg, ONFI_RESET); 234 sc->sc_cmd_reg, ONFI_RESET);
236 235
237 omap2_nand_busy(self); 236 omap2_nand_busy(self);
238 237
239 /* read GPMC_CONFIG1_i to get buswidth */ 238 /* read GPMC_CONFIG1_i to get buswidth */
240 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GPMC_CONFIG1_i); 239 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GPMC_CONFIG1_i);
241 240
242 if ((val & DEVICESIZE) == MASKEDINT(DEVICESIZE, 0x01)) { 241 if ((val & DEVICESIZE) == MASKEDINT(DEVICESIZE, 0x01)) {
243 /* 16bit */ 242 /* 16bit */
244 sc->sc_buswidth = 1; 243 sc->sc_buswidth = 1;
245 } else if ((val & DEVICESIZE) == MASKEDINT(DEVICESIZE, 0x00)) { 244 } else if ((val & DEVICESIZE) == MASKEDINT(DEVICESIZE, 0x00)) {
246 /* 8bit */ 245 /* 8bit */
247 sc->sc_buswidth = 0; 246 sc->sc_buswidth = 0;
248 } else { 247 } else {
249 panic("invalid buswidth reported by config1"); 248 panic("invalid buswidth reported by config1");
250 } 249 }
251 250
252 nand_init_interface(&sc->sc_nand_if); 251 nand_init_interface(&sc->sc_nand_if);
253 252
254 sc->sc_nand_if.command = &omap2_nand_command; 253 sc->sc_nand_if.command = &omap2_nand_command;
255 sc->sc_nand_if.address = &omap2_nand_address; 254 sc->sc_nand_if.address = &omap2_nand_address;
256 sc->sc_nand_if.read_buf_1 = &omap2_nand_read_buf_1; 255 sc->sc_nand_if.read_buf_1 = &omap2_nand_read_buf_1;
257 sc->sc_nand_if.read_buf_2 = &omap2_nand_read_buf_2; 256 sc->sc_nand_if.read_buf_2 = &omap2_nand_read_buf_2;
258 sc->sc_nand_if.read_1 = &omap2_nand_read_1; 257 sc->sc_nand_if.read_1 = &omap2_nand_read_1;
259 sc->sc_nand_if.read_2 = &omap2_nand_read_2; 258 sc->sc_nand_if.read_2 = &omap2_nand_read_2;
260 sc->sc_nand_if.write_buf_1 = &omap2_nand_write_buf_1; 259 sc->sc_nand_if.write_buf_1 = &omap2_nand_write_buf_1;
261 sc->sc_nand_if.write_buf_2 = &omap2_nand_write_buf_2; 260 sc->sc_nand_if.write_buf_2 = &omap2_nand_write_buf_2;
262 sc->sc_nand_if.write_1 = &omap2_nand_write_1; 261 sc->sc_nand_if.write_1 = &omap2_nand_write_1;
263 sc->sc_nand_if.write_2 = &omap2_nand_write_2; 262 sc->sc_nand_if.write_2 = &omap2_nand_write_2;
264 sc->sc_nand_if.busy = &omap2_nand_busy; 263 sc->sc_nand_if.busy = &omap2_nand_busy;
265 264
266#ifdef OMAP2_NAND_HARDWARE_ECC 265#ifdef OMAP2_NAND_HARDWARE_ECC
267 omap2_nand_ecc_init(self); 266 omap2_nand_ecc_init(self);
268 sc->sc_nand_if.ecc_compute = &omap2_nand_ecc_compute; 267 sc->sc_nand_if.ecc_compute = &omap2_nand_ecc_compute;
269 sc->sc_nand_if.ecc_correct = &omap2_nand_ecc_correct; 268 sc->sc_nand_if.ecc_correct = &omap2_nand_ecc_correct;
270 sc->sc_nand_if.ecc_prepare = &omap2_nand_ecc_prepare; 269 sc->sc_nand_if.ecc_prepare = &omap2_nand_ecc_prepare;
271 sc->sc_nand_if.ecc.necc_code_size = 3; 270 sc->sc_nand_if.ecc.necc_code_size = 3;
272 sc->sc_nand_if.ecc.necc_block_size = 512; 271 sc->sc_nand_if.ecc.necc_block_size = 512;
273 sc->sc_nand_if.ecc.necc_type = NAND_ECC_TYPE_HW; 272 sc->sc_nand_if.ecc.necc_type = NAND_ECC_TYPE_HW;
274#else 273#else
275 sc->sc_nand_if.ecc.necc_code_size = 3; 274 sc->sc_nand_if.ecc.necc_code_size = 3;
276 sc->sc_nand_if.ecc.necc_block_size = 256; 275 sc->sc_nand_if.ecc.necc_block_size = 256;
277#endif /* OMAP2_NAND_HARDWARE_ECC */ 276#endif /* OMAP2_NAND_HARDWARE_ECC */
278 277
279 if (!pmf_device_register1(sc->sc_dev, NULL, NULL, NULL)) 278 if (!pmf_device_register1(sc->sc_dev, NULL, NULL, NULL))
280 aprint_error_dev(sc->sc_dev, 279 aprint_error_dev(sc->sc_dev,
281 "couldn't establish power handler\n"); 280 "couldn't establish power handler\n");
282 281
283 sc->sc_nanddev = nand_attach_mi(&sc->sc_nand_if, sc->sc_dev); 282 sc->sc_nanddev = nand_attach_mi(&sc->sc_nand_if, sc->sc_dev);
284} 283}
285 284
286static int 285static int
287omap2_nand_detach(device_t device, int flags) 286omap2_nand_detach(device_t device, int flags)
288{ 287{
289 struct omap2_nand_softc *sc = device_private(device); 288 struct omap2_nand_softc *sc = device_private(device);
290 int ret = 0; 289 int ret = 0;
291 290
292 bus_space_unmap(sc->sc_iot, sc->sc_ioh, GPMC_CS_SIZE); 291 bus_space_unmap(sc->sc_iot, sc->sc_ioh, GPMC_CS_SIZE);
293 292
294 pmf_device_deregister(sc->sc_dev); 293 pmf_device_deregister(sc->sc_dev);
295 294
296 if (sc->sc_nanddev != NULL) 295 if (sc->sc_nanddev != NULL)
297 ret = config_detach(sc->sc_nanddev, flags); 296 ret = config_detach(sc->sc_nanddev, flags);
298 297
299 return ret; 298 return ret;
300} 299}
301 300
302void 301void
303omap2_nand_busy(device_t self) 302omap2_nand_busy(device_t self)
304{ 303{
305 struct omap2_nand_softc *sc = device_private(self); 304 struct omap2_nand_softc *sc = device_private(self);
306 305
307 while (!(gpmc_register_read(sc->sc_gpmcsc, GPMC_STATUS) & WAIT0)) { 306 while (!(gpmc_register_read(sc->sc_gpmcsc, GPMC_STATUS) & WAIT0)) {
308 DELAY(1); 307 DELAY(1);
309 } 308 }
310} 309}
311 310
312void 311void
313omap2_nand_read_1(device_t self, uint8_t *data) 312omap2_nand_read_1(device_t self, uint8_t *data)
314{ 313{
315 struct omap2_nand_softc *sc = device_private(self); 314 struct omap2_nand_softc *sc = device_private(self);
316 315
317 *data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg); 316 *data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg);
318} 317}
319 318
320void 319void
321omap2_nand_write_1(device_t self, uint8_t data) 320omap2_nand_write_1(device_t self, uint8_t data)
322{ 321{
323 struct omap2_nand_softc *sc = device_private(self); 322 struct omap2_nand_softc *sc = device_private(self);
324 323
325 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg, data); 324 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg, data);
326} 325}
327 326
328void 327void
329omap2_nand_read_2(device_t self, uint16_t *data) 328omap2_nand_read_2(device_t self, uint16_t *data)
330{ 329{
331 struct omap2_nand_softc *sc = device_private(self); 330 struct omap2_nand_softc *sc = device_private(self);
332 331
333 *data = bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg); 332 *data = bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg);
334} 333}
335 334
336void 335void
337omap2_nand_write_2(device_t self, uint16_t data) 336omap2_nand_write_2(device_t self, uint16_t data)
338{ 337{
339 struct omap2_nand_softc *sc = device_private(self); 338 struct omap2_nand_softc *sc = device_private(self);
340 339
341 bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg, data); 340 bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg, data);
342} 341}
343 342
344void 343void
345omap2_nand_read_buf_1(device_t self, void *buf, size_t len) 344omap2_nand_read_buf_1(device_t self, void *buf, size_t len)
346{ 345{
347 struct omap2_nand_softc *sc = device_private(self); 346 struct omap2_nand_softc *sc = device_private(self);
348 347
349 KASSERT(buf != NULL); 348 KASSERT(buf != NULL);
350 KASSERT(len >= 1); 349 KASSERT(len >= 1);
351 350
352 bus_space_read_multi_1(sc->sc_iot, sc->sc_ioh, 351 bus_space_read_multi_1(sc->sc_iot, sc->sc_ioh,
353 sc->sc_data_reg, buf, len); 352 sc->sc_data_reg, buf, len);
354} 353}
355 354
356void 355void
357omap2_nand_read_buf_2(device_t self, void *buf, size_t len) 356omap2_nand_read_buf_2(device_t self, void *buf, size_t len)
358{ 357{
359 struct omap2_nand_softc *sc = device_private(self); 358 struct omap2_nand_softc *sc = device_private(self);
360 359
361 KASSERT(buf != NULL); 360 KASSERT(buf != NULL);
362 KASSERT(len >= 2); 361 KASSERT(len >= 2);
363 KASSERT(!(len & 0x01)); 362 KASSERT(!(len & 0x01));
364 363
365 bus_space_read_multi_2(sc->sc_iot, sc->sc_ioh, 364 bus_space_read_multi_2(sc->sc_iot, sc->sc_ioh,
366 sc->sc_data_reg, buf, len / 2); 365 sc->sc_data_reg, buf, len / 2);
367} 366}
368 367
369void 368void
370omap2_nand_write_buf_1(device_t self, const void *buf, size_t len) 369omap2_nand_write_buf_1(device_t self, const void *buf, size_t len)
371{ 370{
372 struct omap2_nand_softc *sc = device_private(self); 371 struct omap2_nand_softc *sc = device_private(self);
373 372
374 KASSERT(buf != NULL); 373 KASSERT(buf != NULL);
375 KASSERT(len >= 1); 374 KASSERT(len >= 1);
376 375
377 bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh, 376 bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh,
378 sc->sc_data_reg, buf, len); 377 sc->sc_data_reg, buf, len);
379} 378}
380 379
381void 380void
382omap2_nand_write_buf_2(device_t self, const void *buf, size_t len) 381omap2_nand_write_buf_2(device_t self, const void *buf, size_t len)
383{ 382{
384 struct omap2_nand_softc *sc = device_private(self); 383 struct omap2_nand_softc *sc = device_private(self);
385 384
386 KASSERT(buf != NULL); 385 KASSERT(buf != NULL);
387 KASSERT(len >= 2); 386 KASSERT(len >= 2);
388 KASSERT(!(len & 0x01)); 387 KASSERT(!(len & 0x01));
389 388
390 bus_space_write_multi_2(sc->sc_iot, sc->sc_ioh, 389 bus_space_write_multi_2(sc->sc_iot, sc->sc_ioh,
391 sc->sc_data_reg, buf, len / 2); 390 sc->sc_data_reg, buf, len / 2);
392} 391}
393 392
394static uint32_t 393static uint32_t
395convert_ecc(const uint8_t *ecc) 394convert_ecc(const uint8_t *ecc)
396{ 395{
397 return ecc[0] | (ecc[1] << 16) | ((ecc[2] & 0xf0) << 20) | 396 return ecc[0] | (ecc[1] << 16) | ((ecc[2] & 0xf0) << 20) |
398 ((ecc[2] & 0x0f) << 8); 397 ((ecc[2] & 0x0f) << 8);
399} 398}
400 399
401int 400int
402omap2_nand_ecc_init(device_t self) 401omap2_nand_ecc_init(device_t self)
403{ 402{
404 struct omap2_nand_softc *sc = device_private(self); 403 struct omap2_nand_softc *sc = device_private(self);
405 uint32_t val; 404 uint32_t val;
406 405
407 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONTROL); 406 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONTROL);
408 /* clear ecc, select ecc register 1 */ 407 /* clear ecc, select ecc register 1 */
409 val &= ~ECCPOINTER; 408 val &= ~ECCPOINTER;
410 val |= ECCCLEAR | MASKEDINT(ECCPOINTER, 1); 409 val |= ECCCLEAR | MASKEDINT(ECCPOINTER, 1);
411 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONTROL, val); 410 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONTROL, val);
412 411
413 /* XXX too many MAGIC */ 412 /* XXX too many MAGIC */
414 /* set ecc size to 512, set all regs to eccsize1*/ 413 /* set ecc size to 512, set all regs to eccsize1*/
415 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_SIZE_CONFIG); 414 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_SIZE_CONFIG);
416 val &= ~ECCSIZE1; 415 val &= ~ECCSIZE1;
417 val |= MASKEDINT(ECCSIZE1, 512) | 0x0f; 416 val |= MASKEDINT(ECCSIZE1, 512) | 0x0f;
418 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONTROL, val); 417 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONTROL, val);
419 418
420 return 0; 419 return 0;
421} 420}
422 421
423int 422int
424omap2_nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *ecc) 423omap2_nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *ecc)
425{ 424{
426 struct omap2_nand_softc *sc = device_private(self); 425 struct omap2_nand_softc *sc = device_private(self);
427 uint32_t val; 426 uint32_t val;
428 427
429 /* read ecc result register */ 428 /* read ecc result register */
430 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC1_RESULT); 429 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC1_RESULT);
431 430
432 ecc[0] = val & 0xff; 431 ecc[0] = val & 0xff;
433 ecc[1] = (val >> 16) & 0xff; 432 ecc[1] = (val >> 16) & 0xff;
434 ecc[2] = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); 433 ecc[2] = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
435 434
436 /* disable ecc engine */ 435 /* disable ecc engine */
437 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONFIG); 436 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONFIG);
438 val &= ~ECCENABLE; 437 val &= ~ECCENABLE;
439 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONFIG, val); 438 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONFIG, val);
440 439
441 return 0; 440 return 0;
442} 441}
443 442
444int 443int
445omap2_nand_ecc_prepare(device_t self, int mode) 444omap2_nand_ecc_prepare(device_t self, int mode)
446{ 445{
447 struct omap2_nand_softc *sc = device_private(self); 446 struct omap2_nand_softc *sc = device_private(self);
448 uint32_t val; 447 uint32_t val;
449 448
450 /* same for read/write */ 449 /* same for read/write */
451 switch (mode) { 450 switch (mode) {
452 case NAND_ECC_READ: 451 case NAND_ECC_READ:
453 case NAND_ECC_WRITE: 452 case NAND_ECC_WRITE:
454 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONTROL); 453 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONTROL);
455 /* clear ecc, select ecc register 1 */ 454 /* clear ecc, select ecc register 1 */
456 val &= ~ECCPOINTER; 455 val &= ~ECCPOINTER;
457 val |= ECCCLEAR | MASKEDINT(ECCPOINTER, 1); 456 val |= ECCCLEAR | MASKEDINT(ECCPOINTER, 1);
458 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONTROL, val); 457 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONTROL, val);
459 458
460 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONFIG); 459 val = gpmc_register_read(sc->sc_gpmcsc, GPMC_ECC_CONFIG);
461 val &= ~ECCCS; 460 val &= ~ECCCS;
462 val |= ECCENABLE | MASKEDINT(ECCCS, sc->sc_cs); 461 val |= ECCENABLE | MASKEDINT(ECCCS, sc->sc_cs);
463 if (sc->sc_buswidth == 1) 462 if (sc->sc_buswidth == 1)
464 val |= ECC16B; 463 val |= ECC16B;
465 else 464 else
466 val &= ~ECC16B; 465 val &= ~ECC16B;
467 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONFIG, val); 466 gpmc_register_write(sc->sc_gpmcsc, GPMC_ECC_CONFIG, val);
468 467
469 break; 468 break;
470 default: 469 default:
471 aprint_error_dev(self, "invalid i/o mode for ecc prepare\n"); 470 aprint_error_dev(self, "invalid i/o mode for ecc prepare\n");
472 return -1; 471 return -1;
473 } 472 }
474 473
475 return 0; 474 return 0;
476} 475}
477 476
478int 477int
479omap2_nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldecc, 478omap2_nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldecc,
480 const uint8_t *calcecc) 479 const uint8_t *calcecc)
481{ 480{
482 uint32_t oecc, cecc, xor; 481 uint32_t oecc, cecc, xor;
483 uint16_t parity, offset; 482 uint16_t parity, offset;
484 uint8_t bit; 483 uint8_t bit;
485 484
486 oecc = convert_ecc(oldecc); 485 oecc = convert_ecc(oldecc);
487 cecc = convert_ecc(calcecc); 486 cecc = convert_ecc(calcecc);
488 487
489 /* get the difference */ 488 /* get the difference */
490 xor = oecc ^ cecc; 489 xor = oecc ^ cecc;
491 490
492 /* the data was correct if all bits are zero */ 491 /* the data was correct if all bits are zero */
493 if (xor == 0x00) 492 if (xor == 0x00)
494 return NAND_ECC_OK; 493 return NAND_ECC_OK;
495 494
496 switch (popcount32(xor)) { 495 switch (popcount32(xor)) {
497 case 12: 496 case 12:
498 /* single byte error */ 497 /* single byte error */
499 parity = xor >> 16; 498 parity = xor >> 16;
500 bit = (parity & 0x07); 499 bit = (parity & 0x07);
501 offset = (parity >> 3) & 0x01ff; 500 offset = (parity >> 3) & 0x01ff;
502 /* correct bit */ 501 /* correct bit */
503 data[offset] ^= (0x01 << bit); 502 data[offset] ^= (0x01 << bit);
504 return NAND_ECC_CORRECTED; 503 return NAND_ECC_CORRECTED;
505 case 1: 504 case 1:
506 return NAND_ECC_INVALID; 505 return NAND_ECC_INVALID;
507 default: 506 default:
508 /* erased page! */ 507 /* erased page! */
509 if ((oecc == 0x0fff0fff) && (cecc == 0x00000000)) 508 if ((oecc == 0x0fff0fff) && (cecc == 0x00000000))
510 return NAND_ECC_OK; 509 return NAND_ECC_OK;
511 510
512 return NAND_ECC_TWOBIT; 511 return NAND_ECC_TWOBIT;
513 } 512 }
514} 513}