Tue Apr 26 17:31:58 2011 UTC ()
it seems we have a config_detach_children (though undocumented)
lets use that to detach flash devices before detaching nand


(ahoka)
diff -r1.9 -r1.10 src/sys/dev/nand/nand.c
diff -r1.7 -r1.8 src/sys/dev/nand/nand.h

cvs diff -r1.9 -r1.10 src/sys/dev/nand/nand.c (expand / switch to unified diff)

--- src/sys/dev/nand/nand.c 2011/04/26 13:38:13 1.9
+++ src/sys/dev/nand/nand.c 2011/04/26 17:31:57 1.10
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: nand.c,v 1.9 2011/04/26 13:38:13 ahoka Exp $ */ 1/* $NetBSD: nand.c,v 1.10 2011/04/26 17:31:57 ahoka 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:
@@ -24,67 +24,62 @@ @@ -24,67 +24,62 @@
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/* Common driver for NAND chips implementing the ONFI 2.2 specification */ 34/* Common driver for NAND chips implementing the ONFI 2.2 specification */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.9 2011/04/26 13:38:13 ahoka Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.10 2011/04/26 17:31:57 ahoka Exp $");
38 38
39#include "locators.h" 39#include "locators.h"
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/types.h> 42#include <sys/types.h>
43#include <sys/device.h> 43#include <sys/device.h>
44#include <sys/kmem.h> 44#include <sys/kmem.h>
45#include <sys/sysctl.h> 45#include <sys/sysctl.h>
46#include <sys/atomic.h> 46#include <sys/atomic.h>
47 47
48#include <dev/flash/flash.h> 48#include <dev/flash/flash.h>
49#include <dev/nand/nand.h> 49#include <dev/nand/nand.h>
50#include <dev/nand/onfi.h> 50#include <dev/nand/onfi.h>
51#include <dev/nand/hamming.h> 51#include <dev/nand/hamming.h>
52#include <dev/nand/nand_bbt.h> 52#include <dev/nand/nand_bbt.h>
53#include <dev/nand/nand_crc.h> 53#include <dev/nand/nand_crc.h>
54 54
55#include "opt_nand.h" 55#include "opt_nand.h"
56 56
57int nand_match(device_t, cfdata_t, void *); 57int nand_match(device_t, cfdata_t, void *);
58void nand_attach(device_t, device_t, void *); 58void nand_attach(device_t, device_t, void *);
59int nand_detach(device_t, int); 59int nand_detach(device_t, int);
60bool nand_shutdown(device_t, int); 60bool nand_shutdown(device_t, int);
61void nand_childdet(device_t, device_t); 
62 61
63int nand_print(void *, const char *); 62int nand_print(void *, const char *);
64 63
65static int nand_search(device_t, cfdata_t, const int *, void *); 64static int nand_search(device_t, cfdata_t, const int *, void *);
66static void nand_address_row(device_t, size_t); 65static void nand_address_row(device_t, size_t);
67static void nand_address_column(device_t, size_t, size_t); 66static void nand_address_column(device_t, size_t, size_t);
68static int nand_fill_chip_structure(device_t, struct nand_chip *); 67static int nand_fill_chip_structure(device_t, struct nand_chip *);
69static int nand_scan_media(device_t, struct nand_chip *); 68static int nand_scan_media(device_t, struct nand_chip *);
70static bool nand_check_wp(device_t); 69static bool nand_check_wp(device_t);
71 70
72CFATTACH_DECL2_NEW(nand, sizeof(struct nand_softc), 71CFATTACH_DECL_NEW(nand, sizeof(struct nand_softc),
73 nand_match, nand_attach, nand_detach, 72 nand_match, nand_attach, nand_detach, NULL);
74 NULL, NULL, nand_childdet); 
75 
76//CFATTACH_DECL_NEW(nand, sizeof(struct nand_softc), 
77// nand_match, nand_attach, nand_detach, NULL); 
78 73
79#ifdef NAND_DEBUG 74#ifdef NAND_DEBUG
80int nanddebug = NAND_DEBUG; 75int nanddebug = NAND_DEBUG;
81#endif 76#endif
82 77
83int nand_cachesync_timeout = 1; 78int nand_cachesync_timeout = 1;
84int nand_cachesync_nodenum; 79int nand_cachesync_nodenum;
85 80
86#ifdef NAND_VERBOSE 81#ifdef NAND_VERBOSE
87const struct nand_manufacturer nand_mfrs[] = { 82const struct nand_manufacturer nand_mfrs[] = {
88 { NAND_MFR_AMD, "AMD" }, 83 { NAND_MFR_AMD, "AMD" },
89 { NAND_MFR_FUJITSU, "Fujitsu" }, 84 { NAND_MFR_FUJITSU, "Fujitsu" },
90 { NAND_MFR_RENESAS, "Renesas" }, 85 { NAND_MFR_RENESAS, "Renesas" },
@@ -122,28 +117,26 @@ nand_match(device_t parent, cfdata_t mat @@ -122,28 +117,26 @@ nand_match(device_t parent, cfdata_t mat
122} 117}
123 118
124void 119void
125nand_attach(device_t parent, device_t self, void *aux) 120nand_attach(device_t parent, device_t self, void *aux)
126{ 121{
127 struct nand_softc *sc = device_private(self); 122 struct nand_softc *sc = device_private(self);
128 struct nand_attach_args *naa = aux; 123 struct nand_attach_args *naa = aux;
129 struct nand_chip *chip = &sc->sc_chip; 124 struct nand_chip *chip = &sc->sc_chip;
130 125
131 sc->sc_dev = self; 126 sc->sc_dev = self;
132 sc->controller_dev = parent; 127 sc->controller_dev = parent;
133 sc->nand_if = naa->naa_nand_if; 128 sc->nand_if = naa->naa_nand_if;
134 129
135 sc->sc_children = 0; 
136 
137 aprint_naive("\n"); 130 aprint_naive("\n");
138 131
139 if (nand_check_wp(self)) { 132 if (nand_check_wp(self)) {
140 aprint_error("NAND chip is write protected!\n"); 133 aprint_error("NAND chip is write protected!\n");
141 return; 134 return;
142 } 135 }
143  136
144 if (nand_scan_media(self, chip)) { 137 if (nand_scan_media(self, chip)) {
145 return; 138 return;
146 } 139 }
147 140
148 /* allocate cache */ 141 /* allocate cache */
149 chip->nc_oob_cache = kmem_alloc(chip->nc_spare_size, KM_SLEEP); 142 chip->nc_oob_cache = kmem_alloc(chip->nc_spare_size, KM_SLEEP);
@@ -210,72 +203,63 @@ nand_search(device_t parent, cfdata_t cf @@ -210,72 +203,63 @@ nand_search(device_t parent, cfdata_t cf
210 flash_if->size = cf->cf_loc[FLASHBUSCF_SIZE]; 203 flash_if->size = cf->cf_loc[FLASHBUSCF_SIZE];
211 flash_if->partition.part_size = cf->cf_loc[FLASHBUSCF_SIZE]; 204 flash_if->partition.part_size = cf->cf_loc[FLASHBUSCF_SIZE];
212 } 205 }
213 206
214 if (cf->cf_loc[FLASHBUSCF_READONLY]) 207 if (cf->cf_loc[FLASHBUSCF_READONLY])
215 flash_if->partition.part_flags = FLASH_PART_READONLY; 208 flash_if->partition.part_flags = FLASH_PART_READONLY;
216 else 209 else
217 flash_if->partition.part_flags = 0; 210 flash_if->partition.part_flags = 0;
218 211
219 faa.flash_if = flash_if; 212 faa.flash_if = flash_if;
220 213
221 if (config_match(parent, cf, &faa)) { 214 if (config_match(parent, cf, &faa)) {
222 if (config_attach(parent, cf, &faa, nand_print) != NULL) { 215 if (config_attach(parent, cf, &faa, nand_print) != NULL) {
223 atomic_inc_uint(&sc->sc_children); 
224 return 0; 216 return 0;
225 } else { 217 } else {
226 return 1; 218 return 1;
227 } 219 }
228 } else { 220 } else {
229 kmem_free(flash_if, sizeof(*flash_if)); 221 kmem_free(flash_if, sizeof(*flash_if));
230 } 222 }
231 223
232 return 1; 224 return 1;
233} 225}
234 226
235int 227int
236nand_detach(device_t self, int flags) 228nand_detach(device_t self, int flags)
237{ 229{
238 struct nand_softc *sc = device_private(self); 230 struct nand_softc *sc = device_private(self);
239 struct nand_chip *chip = &sc->sc_chip; 231 struct nand_chip *chip = &sc->sc_chip;
240 int ret = 0; 232 int error = 0;
241 233
242 if (sc->sc_children != 0) { 234 error = config_detach_children(self, flags);
243 return EBUSY; 235 if (error) {
 236 return error;
244 } 237 }
245 238
246 nand_sync_thread_stop(self); 239 nand_sync_thread_stop(self);
247#ifdef NAND_BBT 240#ifdef NAND_BBT
248 nand_bbt_detach(self); 241 nand_bbt_detach(self);
249#endif 242#endif
250 /* free oob cache */ 243 /* free oob cache */
251 kmem_free(chip->nc_oob_cache, chip->nc_spare_size); 244 kmem_free(chip->nc_oob_cache, chip->nc_spare_size);
252 kmem_free(chip->nc_page_cache, chip->nc_page_size); 245 kmem_free(chip->nc_page_cache, chip->nc_page_size);
253 kmem_free(chip->nc_ecc_cache, chip->nc_ecc->necc_size); 246 kmem_free(chip->nc_ecc_cache, chip->nc_ecc->necc_size);
254 247
255 mutex_destroy(&sc->sc_device_lock); 248 mutex_destroy(&sc->sc_device_lock);
256 249
257 pmf_device_deregister(sc->sc_dev); 250 pmf_device_deregister(sc->sc_dev);
258 251
259 return ret; 252 return error;
260} 
261 
262void 
263nand_childdet(device_t self, device_t child) 
264{ 
265 struct nand_softc *sc = device_private(self); 
266 
267 atomic_dec_uint(&sc->sc_children); 
268 KASSERT(sc->sc_children >= 0); 
269} 253}
270 254
271int 255int
272nand_print(void *aux, const char *pnp) 256nand_print(void *aux, const char *pnp)
273{ 257{
274 if (pnp != NULL) 258 if (pnp != NULL)
275 aprint_normal("nand at %s\n", pnp); 259 aprint_normal("nand at %s\n", pnp);
276 260
277 return UNCONF; 261 return UNCONF;
278} 262}
279 263
280/* ask for a nand driver to attach to the controller */ 264/* ask for a nand driver to attach to the controller */
281device_t 265device_t

cvs diff -r1.7 -r1.8 src/sys/dev/nand/nand.h (expand / switch to unified diff)

--- src/sys/dev/nand/nand.h 2011/04/26 13:38:13 1.7
+++ src/sys/dev/nand/nand.h 2011/04/26 17:31:57 1.8
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: nand.h,v 1.7 2011/04/26 13:38:13 ahoka Exp $ */ 1/* $NetBSD: nand.h,v 1.8 2011/04/26 17:31:57 ahoka 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:
@@ -151,33 +151,26 @@ struct nand_softc { @@ -151,33 +151,26 @@ struct nand_softc {
151 void *nand_softc; 151 void *nand_softc;
152 struct nand_chip sc_chip; 152 struct nand_chip sc_chip;
153 struct nand_bbt sc_bbt; 153 struct nand_bbt sc_bbt;
154 size_t sc_part_offset; 154 size_t sc_part_offset;
155 size_t sc_part_size; 155 size_t sc_part_size;
156 kmutex_t sc_device_lock; /* serialize access to chip */ 156 kmutex_t sc_device_lock; /* serialize access to chip */
157 157
158 /* for the i/o thread */ 158 /* for the i/o thread */
159 struct lwp *sc_sync_thread; 159 struct lwp *sc_sync_thread;
160 struct nand_write_cache sc_cache; 160 struct nand_write_cache sc_cache;
161 kmutex_t sc_io_lock; 161 kmutex_t sc_io_lock;
162 kcondvar_t sc_io_cv; 162 kcondvar_t sc_io_cv;
163 bool sc_io_running; 163 bool sc_io_running;
164 
165 /* currently we cant automatically detach children 
166 * so keep count of attached children so we will 
167 * know, that when is safe to detach... 
168 * XXX is it a problem only as a module? (ioconf bug?) 
169 */ 
170 unsigned int sc_children; 
171}; 164};
172 165
173/* structure holding the nand api */ 166/* structure holding the nand api */
174struct nand_interface 167struct nand_interface
175{ 168{
176 /* basic nand controller commands */ 169 /* basic nand controller commands */
177 void (*select) (device_t, bool); /* optional */ 170 void (*select) (device_t, bool); /* optional */
178 void (*command) (device_t, uint8_t); 171 void (*command) (device_t, uint8_t);
179 void (*address) (device_t, uint8_t); 172 void (*address) (device_t, uint8_t);
180 void (*read_buf_byte) (device_t, void *, size_t); 173 void (*read_buf_byte) (device_t, void *, size_t);
181 void (*read_buf_word) (device_t, void *, size_t); 174 void (*read_buf_word) (device_t, void *, size_t);
182 void (*read_byte) (device_t, uint8_t *); 175 void (*read_byte) (device_t, uint8_t *);
183 void (*read_word) (device_t, uint16_t *); 176 void (*read_word) (device_t, uint16_t *);