1193323Sed/* $NetBSD: nor.h,v 1.5 2018/04/19 21:50:09 christos Exp $ */ 2193323Sed 3193323Sed/*- 4193323Sed * Copyright (c) 2011 Department of Software Engineering, 5193323Sed * University of Szeged, Hungary 6193323Sed * Copyright (c) 2011 Adam Hoka <ahoka@NetBSD.org> 7193323Sed * All rights reserved. 8193323Sed * 9193323Sed * This code is derived from software contributed to The NetBSD Foundation 10193323Sed * by the Department of Software Engineering, University of Szeged, Hungary 11193323Sed * 12193323Sed * Redistribution and use in source and binary forms, with or without 13193323Sed * modification, are permitted provided that the following conditions 14193323Sed * are met: 15193323Sed * 1. Redistributions of source code must retain the above copyright 16193323Sed * notice, this list of conditions and the following disclaimer. 17193323Sed * 2. Redistributions in binary form must reproduce the above copyright 18193323Sed * notice, this list of conditions and the following disclaimer in the 19193323Sed * documentation and/or other materials provided with the distribution. 20193323Sed * 21218893Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23193323Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24193323Sed * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25193323Sed * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26202375Srdivacky * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27193323Sed * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28193323Sed * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29193323Sed * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31193323Sed * SUCH DAMAGE. 32193323Sed */ 33193323Sed 34195340Sed#ifndef _NOR_H_ 35195340Sed#define _NOR_H_ 36203954Srdivacky 37193323Sed#include <sys/param.h> 38193323Sed#include <sys/cdefs.h> 39193323Sed 40193323Sed#include <sys/bufq.h> 41193323Sed#include <sys/buf.h> 42193323Sed#include <sys/device.h> 43193323Sed 44193323Sed#include <sys/bus.h> 45198090Srdivacky 46193323Sed#include <dev/flash/flash.h> 47193323Sed#include <dev/flash/flash_io.h> 48193323Sed 49193323Sed#ifdef NOR_DEBUG 50193323Sed#define DPRINTF(x) do { printf x ; } while (0) 51221345Sdim#else 52193323Sed#define DPRINTF(x) 53193323Sed#endif 54193323Sed 55193323Sed/** 56193323Sed * nor_chip: structure containing the required information 57193323Sed * about the NOR chip. 58193323Sed */ 59193323Sedstruct nor_chip { 60193323Sed struct nor_ecc *nc_ecc; /* ecc information */ 61193323Sed uint8_t *nc_oob_cache; /* buffer for oob cache */ 62193323Sed uint8_t *nc_page_cache; /* buffer for page cache */ 63193323Sed uint8_t *nc_ecc_cache; 64193323Sed size_t nc_size; /* storage size in bytes */ 65193323Sed size_t nc_page_size; /* page (write buf) size in bytes */ 66195340Sed size_t nc_line_size; /* read line in bytes */ 67195340Sed size_t nc_block_pages; /* block size in pages */ 68203954Srdivacky size_t nc_block_size; /* block size in bytes */ 69203954Srdivacky size_t nc_spare_size; /* spare (oob) size in bytes */ 70193323Sed uint32_t nc_lun_blocks; /* LUN size in blocks */ 71193323Sed uint32_t nc_flags; /* bitfield flags */ 72193323Sed uint32_t nc_quirks; /* bitfield quirks */ 73193323Sed unsigned int nc_page_shift; /* page shift for page alignment */ 74193323Sed unsigned int nc_page_mask; /* page mask for page alignment */ 75193323Sed unsigned int nc_block_shift; /* write shift */ 76193323Sed unsigned int nc_block_mask; /* write mask */ 77193323Sed uint8_t nc_num_luns; /* number of LUNs */ 78193323Sed uint8_t nc_manf_id; /* manufacturer id */ 79193323Sed uint8_t nc_dev_id; /* device id */ 80193323Sed uint8_t nc_badmarker_offs; /* offset for marking bad blocks */ 81193323Sed}; 82193323Sed 83193323Sed/* driver softc for nor */ 84193323Sedstruct nor_softc { 85195098Sed device_t sc_dev; 86195098Sed device_t sc_controller_dev; 87195098Sed struct flash_interface sc_flash_if; 88193323Sed struct nor_interface *sc_nor_if; 89193323Sed void *nor_softc; 90193323Sed struct nor_chip sc_chip; 91223017Sdim bus_addr_t sc_bus_addr; /* chip base address */ 92193323Sed bus_size_t sc_bus_size; /* total NOR size */ 93193323Sed off_t sc_part_offset; /* partition start, offset from base */ 94193323Sed size_t sc_part_size; /* partition size */ 95193323Sed bus_space_tag_t sc_bst; 96193323Sed bus_space_handle_t sc_bsh; 97195098Sed kmutex_t sc_device_lock; /* serialize access to chip */ 98195098Sed struct flash_io sc_flash_io; 99195098Sed}; 100193323Sed 101193323Sed/* structure holding the nor api */ 102193323Sedstruct nor_interface { 103195098Sed /* basic nor controller commands */ 104195098Sed int (*scan_media)(device_t self, struct nor_chip *chip); 105195098Sed void (*init) (device_t); 106193323Sed void (*select) (device_t, bool); /* optional */ 107193323Sed void (*read_1) (device_t, flash_off_t, uint8_t *); 108193323Sed void (*read_2) (device_t, flash_off_t, uint16_t *); 109207618Srdivacky void (*read_4) (device_t, flash_off_t, uint32_t *); 110195098Sed void (*read_buf_1) (device_t, flash_off_t, uint8_t *, size_t); 111195098Sed void (*read_buf_2) (device_t, flash_off_t, uint16_t *, size_t); 112195098Sed void (*read_buf_4) (device_t, flash_off_t, uint32_t *, size_t); 113193323Sed void (*write_1) (device_t, flash_off_t, uint8_t); 114193323Sed void (*write_2) (device_t, flash_off_t, uint16_t); 115193323Sed void (*write_4) (device_t, flash_off_t, uint32_t); 116193323Sed void (*write_buf_1) (device_t, flash_off_t, const uint8_t *, size_t); 117195098Sed void (*write_buf_2) (device_t, flash_off_t, const uint16_t *, size_t); 118198090Srdivacky void (*write_buf_4) (device_t, flash_off_t, const uint32_t *, size_t); 119193323Sed int (*busy) (device_t, flash_off_t, u_long); 120193323Sed 121193323Sed int (*read_page) (device_t, flash_off_t, uint8_t *); 122198090Srdivacky int (*program_page) (device_t, flash_off_t, const uint8_t *); 123193323Sed int (*erase_block) (device_t, flash_off_t); 124193323Sed int (*erase_all) (device_t); 125193323Sed 126193323Sed void *private; /* where to attach e.g. struct cfi */ 127218893Sdim int access_width; /* x8/x16/x32: 1/2/4 */ 128218893Sdim 129218893Sdim /* flash partition information */ 130218893Sdim const struct flash_partition *part_info; 131218893Sdim int part_num; 132218893Sdim}; 133218893Sdim 134193323Sed/* attach args */ 135195098Sedstruct nor_attach_args { 136193323Sed struct nor_interface *naa_nor_if; 137193323Sed}; 138202375Srdivacky 139204642Srdivackystatic __inline bool 140202375Srdivackynor_busy(device_t device, flash_off_t offset, u_long usec) 141202375Srdivacky{ 142202375Srdivacky struct nor_softc *sc = device_private(device); 143205218Srdivacky bool rv; 144205218Srdivacky 145205218Srdivacky KASSERT(sc->sc_nor_if->select != NULL); 146205218Srdivacky KASSERT(sc->sc_controller_dev != NULL); 147205218Srdivacky 148218893Sdim sc->sc_nor_if->select(sc->sc_controller_dev, true); 149221345Sdim 150221345Sdim if (sc->sc_nor_if->busy != NULL) { 151221345Sdim rv = sc->sc_nor_if->busy(sc->sc_controller_dev, offset, usec); 152221345Sdim } else { 153221345Sdim DELAY(usec); 154221345Sdim rv = false; 155221345Sdim } 156221345Sdim 157221345Sdim sc->sc_nor_if->select(sc->sc_controller_dev, false); 158221345Sdim 159218893Sdim return rv; 160218893Sdim} 161218893Sdim 162218893Sdimstatic __inline void 163218893Sdimnor_select(device_t self, bool enable) 164218893Sdim{ 165218893Sdim struct nor_softc *sc = device_private(self); 166218893Sdim 167218893Sdim KASSERT(sc->sc_nor_if->select != NULL); 168218893Sdim KASSERT(sc->sc_controller_dev != NULL); 169218893Sdim 170218893Sdim sc->sc_nor_if->select(sc->sc_controller_dev, enable); 171193323Sed} 172193323Sed 173193323Sedstatic __inline void 174193323Sednor_read_1(device_t self, flash_off_t offset, uint8_t *data) 175193323Sed{ 176193323Sed struct nor_softc *sc = device_private(self); 177193323Sed 178193323Sed KASSERT(sc->sc_nor_if->read_1 != NULL); 179193323Sed KASSERT(sc->sc_controller_dev != NULL); 180193323Sed 181193323Sed sc->sc_nor_if->read_1(sc->sc_controller_dev, offset, data); 182193323Sed} 183193323Sed 184193323Sedstatic __inline void 185193323Sednor_read_2(device_t self, flash_off_t offset, uint16_t *data) 186193323Sed{ 187193323Sed struct nor_softc *sc = device_private(self); 188193323Sed 189193323Sed KASSERT(sc->sc_nor_if->read_2 != NULL); 190193323Sed KASSERT(sc->sc_controller_dev != NULL); 191193323Sed 192193323Sed sc->sc_nor_if->read_2(sc->sc_controller_dev, offset, data); 193193323Sed} 194193323Sed 195193323Sedstatic __inline void 196193323Sednor_read_4(device_t self, flash_off_t offset, uint32_t *data) 197193323Sed{ 198193323Sed struct nor_softc *sc = device_private(self); 199193323Sed 200193323Sed KASSERT(sc->sc_nor_if->read_4 != NULL); 201193323Sed KASSERT(sc->sc_controller_dev != NULL); 202193323Sed 203193323Sed sc->sc_nor_if->read_4(sc->sc_controller_dev, offset, data); 204193323Sed} 205193323Sed 206193323Sedstatic __inline void 207193323Sednor_write_1(device_t self, flash_off_t offset, uint8_t data) 208193323Sed{ 209193323Sed struct nor_softc *sc = device_private(self); 210193323Sed 211193323Sed KASSERT(sc->sc_nor_if->write_1 != NULL); 212193323Sed KASSERT(sc->sc_controller_dev != NULL); 213193323Sed 214193323Sed sc->sc_nor_if->write_1(sc->sc_controller_dev, offset, data); 215193323Sed} 216193323Sed 217193323Sedstatic __inline void 218193323Sednor_write_2(device_t self, flash_off_t offset, uint16_t data) 219193323Sed{ 220193323Sed struct nor_softc *sc = device_private(self); 221193323Sed 222193323Sed KASSERT(sc->sc_nor_if->write_2 != NULL); 223193323Sed KASSERT(sc->sc_controller_dev != NULL); 224193323Sed 225193323Sed sc->sc_nor_if->write_2(sc->sc_controller_dev, offset, data); 226193323Sed} 227193323Sed 228193323Sedstatic __inline void 229193323Sednor_write_4(device_t self, flash_off_t offset, uint16_t data) 230193323Sed{ 231193323Sed struct nor_softc *sc = device_private(self); 232198090Srdivacky 233193323Sed KASSERT(sc->sc_nor_if->write_4 != NULL); 234193323Sed KASSERT(sc->sc_controller_dev != NULL); 235193323Sed 236193323Sed sc->sc_nor_if->write_4(sc->sc_controller_dev, offset, data); 237193323Sed} 238193323Sed 239193323Sedstatic __inline void 240193323Sednor_read_buf_1(device_t self, flash_off_t offset, void *buf, size_t size) 241193323Sed{ 242193323Sed struct nor_softc *sc = device_private(self); 243193323Sed 244193323Sed KASSERT(sc->sc_nor_if->read_buf_1 != NULL); 245193323Sed KASSERT(sc->sc_controller_dev != NULL); 246193323Sed 247193323Sed sc->sc_nor_if->read_buf_1(sc->sc_controller_dev, offset, buf, size); 248193323Sed} 249193323Sed 250193323Sedstatic __inline void 251193323Sednor_read_buf_2(device_t self, flash_off_t offset, void *buf, size_t size) 252193323Sed{ 253195340Sed struct nor_softc *sc = device_private(self); 254195340Sed 255195340Sed KASSERT(sc->sc_nor_if->read_buf_2 != NULL); 256193323Sed KASSERT(sc->sc_controller_dev != NULL); 257193323Sed 258193323Sed sc->sc_nor_if->read_buf_2(sc->sc_controller_dev, offset, buf, size); 259193323Sed} 260 261static __inline void 262nor_read_buf_4(device_t self, flash_off_t offset, void *buf, size_t size) 263{ 264 struct nor_softc *sc = device_private(self); 265 266 KASSERT(sc->sc_nor_if->read_buf_4 != NULL); 267 KASSERT(sc->sc_controller_dev != NULL); 268 269 sc->sc_nor_if->read_buf_4(sc->sc_controller_dev, offset, buf, size); 270} 271 272static __inline void 273nor_write_buf_1(device_t self, flash_off_t offset, const void *buf, size_t size) 274{ 275 struct nor_softc *sc = device_private(self); 276 277 KASSERT(sc->sc_nor_if->write_buf_1 != NULL); 278 KASSERT(sc->sc_controller_dev != NULL); 279 280 sc->sc_nor_if->write_buf_1(sc->sc_controller_dev, offset, buf, size); 281} 282 283static __inline void 284nor_write_buf_2(device_t self, flash_off_t offset, const void *buf, size_t size) 285{ 286 struct nor_softc *sc = device_private(self); 287 288 KASSERT(sc->sc_nor_if->write_buf_2 != NULL); 289 KASSERT(sc->sc_controller_dev != NULL); 290 291 sc->sc_nor_if->write_buf_2(sc->sc_controller_dev, offset, buf, size); 292} 293 294static __inline void 295nor_write_buf_4(device_t self, flash_off_t offset, const void *buf, size_t size) 296{ 297 struct nor_softc *sc = device_private(self); 298 299 KASSERT(sc->sc_nor_if->write_buf_4 != NULL); 300 KASSERT(sc->sc_controller_dev != NULL); 301 302 sc->sc_nor_if->write_buf_4(sc->sc_controller_dev, offset, buf, size); 303} 304 305static __inline int 306nor_read_page(device_t self, flash_off_t offset, uint8_t *data) 307{ 308 struct nor_softc *sc = device_private(self); 309 310 KASSERT(sc->sc_nor_if->read_page != NULL); 311 312 return sc->sc_nor_if->read_page(self, offset, data); 313} 314 315static __inline int 316nor_program_page(device_t self, flash_off_t offset, const uint8_t *data) 317{ 318 struct nor_softc *sc = device_private(self); 319 320 KASSERT(sc->sc_nor_if->program_page != NULL); 321 322 return sc->sc_nor_if->program_page(self, offset, data); 323} 324 325static __inline int 326nor_erase_all(device_t self) 327{ 328 struct nor_softc *sc = device_private(self); 329 330 KASSERT(sc->sc_nor_if->erase_all != NULL); 331 332 return sc->sc_nor_if->erase_all(self); 333} 334 335static __inline int 336nor_erase_block(device_t self, flash_off_t offset) 337{ 338 struct nor_softc *sc = device_private(self); 339 340 KASSERT(sc->sc_nor_if->erase_block != NULL); 341 342 return sc->sc_nor_if->erase_block(self, offset); 343} 344 345/* Manufacturer IDs defined by JEDEC */ 346enum { 347 NOR_MFR_UNKNOWN = 0x00, 348 NOR_MFR_AMD = 0x01, 349 NOR_MFR_FUJITSU = 0x04, 350 NOR_MFR_RENESAS = 0x07, 351 NOR_MFR_STMICRO = 0x20, 352 NOR_MFR_MICRON = 0x2c, 353 NOR_MFR_NATIONAL = 0x8f, 354 NOR_MFR_TOSHIBA = 0x98, 355 NOR_MFR_HYNIX = 0xad, 356 NOR_MFGR_MACRONIX = 0xc2, 357 NOR_MFR_SAMSUNG = 0xec 358}; 359 360struct nor_manufacturer { 361 int id; 362 const char *name; 363}; 364 365extern const struct nor_manufacturer nor_mfrs[]; 366 367/* public nor specific functions */ 368device_t nor_attach_mi(struct nor_interface *, device_t); 369void nor_init_interface(struct nor_interface *); 370 371 372#endif /* _NOR_H_ */ 373