Date: Fri, 16 Jun 2017 09:21:22 +0200 From: Sebastian Huber <sebastian.huber@embedded-brains.de> To: freebsd-hackers@freebsd.org Subject: [PATCH 2/2] cfi: Refactor cfi_write_block() Message-ID: <20170616072122.17504-2-sebastian.huber@embedded-brains.de> In-Reply-To: <20170616072122.17504-1-sebastian.huber@embedded-brains.de> References: <20170616072122.17504-1-sebastian.huber@embedded-brains.de>
next in thread | previous in thread | raw e-mail | index | archive | help
Split up cfi_write_block() into re-usable functions to make it easier to use this code in other systems. --- sys/dev/cfi/cfi_core.c | 199 ++++++++++++++++++++++++++++--------------------- 1 file changed, 114 insertions(+), 85 deletions(-) diff --git a/sys/dev/cfi/cfi_core.c b/sys/dev/cfi/cfi_core.c index e90db06dcef..be596a7e4ab 100644 --- a/sys/dev/cfi/cfi_core.c +++ b/sys/dev/cfi/cfi_core.c @@ -570,121 +570,134 @@ cfi_wait_ready(struct cfi_softc *sc, u_int ofs, sbintime_t start, return (error); } -int -cfi_write_block(struct cfi_softc *sc) +static void +cfi_unlock_flash(struct cfi_softc *sc, u_int ofs) { - union { - uint8_t *x8; - uint16_t *x16; - uint32_t *x32; - } ptr, cpyprt; - register_t intr; - int error, i, neederase = 0; - uint32_t st; - u_int wlen; - sbintime_t start; /* Intel flash must be unlocked before modification */ switch (sc->sc_cmdset) { case CFI_VEND_INTEL_ECS: case CFI_VEND_INTEL_SCS: - cfi_write(sc, sc->sc_wrofs, CFI_INTEL_LBS); - cfi_write(sc, sc->sc_wrofs, CFI_INTEL_UB); - cfi_write(sc, sc->sc_wrofs, CFI_BCS_READ_ARRAY); + cfi_write(sc, ofs, CFI_INTEL_LBS); + cfi_write(sc, ofs, CFI_INTEL_UB); + cfi_write(sc, ofs, CFI_BCS_READ_ARRAY); break; } +} - /* Check if an erase is required. */ - for (i = 0; i < sc->sc_wrbufsz; i++) - if ((sc->sc_wrbuf[i] & sc->sc_wrbufcpy[i]) != sc->sc_wrbuf[i]) { - neederase = 1; - break; - } +static void +cfi_relock_flash(struct cfi_softc *sc, u_int ofs) +{ - if (neederase) { - intr = intr_disable(); - start = sbinuptime(); - /* Erase the block. */ - switch (sc->sc_cmdset) { - case CFI_VEND_INTEL_ECS: - case CFI_VEND_INTEL_SCS: - cfi_write(sc, sc->sc_wrofs, CFI_BCS_BLOCK_ERASE); - cfi_write(sc, sc->sc_wrofs, CFI_BCS_CONFIRM); - break; - case CFI_VEND_AMD_SCS: - case CFI_VEND_AMD_ECS: - cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START, - CFI_AMD_ERASE_SECTOR); - cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE); - break; - default: - /* Better safe than sorry... */ - intr_restore(intr); - return (ENODEV); - } + /* Relock Intel flash */ + switch (sc->sc_cmdset) { + case CFI_VEND_INTEL_ECS: + case CFI_VEND_INTEL_SCS: + cfi_write(sc, ofs, CFI_INTEL_LBS); + cfi_write(sc, ofs, CFI_INTEL_LB); + cfi_write(sc, ofs, CFI_BCS_READ_ARRAY); + break; + } +} + +static int +cfi_erase_block(struct cfi_softc *sc, u_int ofs) +{ + register_t intr; + sbintime_t start; + + intr = intr_disable(); + start = sbinuptime(); + /* Erase the block. */ + switch (sc->sc_cmdset) { + case CFI_VEND_INTEL_ECS: + case CFI_VEND_INTEL_SCS: + cfi_write(sc, ofs, CFI_BCS_BLOCK_ERASE); + cfi_write(sc, ofs, CFI_BCS_CONFIRM); + break; + case CFI_VEND_AMD_SCS: + case CFI_VEND_AMD_ECS: + cfi_amd_write(sc, ofs, AMD_ADDR_START, + CFI_AMD_ERASE_SECTOR); + cfi_amd_write(sc, ofs, 0, CFI_AMD_BLOCK_ERASE); + break; + default: + /* Better safe than sorry... */ intr_restore(intr); - error = cfi_wait_ready(sc, sc->sc_wrofs, start, - CFI_TIMEOUT_ERASE); - if (error) - goto out; - } else - error = 0; + return (ENODEV); + } + intr_restore(intr); + return (cfi_wait_ready(sc, ofs, start, CFI_TIMEOUT_ERASE)); +} + +static int +cfi_program_block(struct cfi_softc *sc, u_int ofs, const u_char *wrbuf, + const u_char *wrbufcpy, u_int wrbufsz, int neederase) +{ + union { + const uint8_t *x8; + const uint16_t *x16; + const uint32_t *x32; + } ptr, cpyprt; + register_t intr; + int error = 0; + uint32_t st; + u_int i, wlen; + sbintime_t start; /* Write the block using a multibyte write if supported. */ - ptr.x8 = sc->sc_wrbuf; - cpyprt.x8 = sc->sc_wrbufcpy; + ptr.x8 = wrbuf; + cpyprt.x8 = wrbufcpy; if (sc->sc_maxbuf > sc->sc_width) { switch (sc->sc_cmdset) { case CFI_VEND_INTEL_ECS: case CFI_VEND_INTEL_SCS: - for (i = 0; i < sc->sc_wrbufsz; i += wlen) { - wlen = MIN(sc->sc_maxbuf, sc->sc_wrbufsz - i); + for (i = 0; i < wrbufsz; i += wlen) { + wlen = MIN(sc->sc_maxbuf, wrbufsz - i); intr = intr_disable(); start = sbinuptime(); do { - cfi_write(sc, sc->sc_wrofs + i, + cfi_write(sc, ofs + i, CFI_BCS_BUF_PROG_SETUP); if (sbinuptime() > start + sc->sc_max_timeouts[CFI_TIMEOUT_BUFWRITE]) { intr_restore(intr); - error = ETIMEDOUT; - goto out; + return (ETIMEDOUT); } - st = cfi_read(sc, sc->sc_wrofs + i); + st = cfi_read(sc, ofs + i); } while (! (st & CFI_INTEL_STATUS_WSMS)); - cfi_write(sc, sc->sc_wrofs + i, + cfi_write(sc, ofs + i, (wlen / sc->sc_width) - 1); switch (sc->sc_width) { case 1: bus_space_write_region_1(sc->sc_tag, - sc->sc_handle, sc->sc_wrofs + i, + sc->sc_handle, ofs + i, ptr.x8 + i, wlen); break; case 2: bus_space_write_region_2(sc->sc_tag, - sc->sc_handle, sc->sc_wrofs + i, + sc->sc_handle, ofs + i, ptr.x16 + i / 2, wlen / 2); break; case 4: bus_space_write_region_4(sc->sc_tag, - sc->sc_handle, sc->sc_wrofs + i, + sc->sc_handle, ofs + i, ptr.x32 + i / 4, wlen / 4); break; } - cfi_write(sc, sc->sc_wrofs + i, - CFI_BCS_CONFIRM); + cfi_write(sc, ofs + i, CFI_BCS_CONFIRM); intr_restore(intr); - error = cfi_wait_ready(sc, sc->sc_wrofs + i, - start, CFI_TIMEOUT_BUFWRITE); + error = cfi_wait_ready(sc, ofs + i, start, + CFI_TIMEOUT_BUFWRITE); if (error != 0) - goto out; + return (error); } - goto out; + return (error); default: /* Fall through to single word case */ break; @@ -693,7 +706,7 @@ cfi_write_block(struct cfi_softc *sc) } /* Write the block one byte/word at a time. */ - for (i = 0; i < sc->sc_wrbufsz; i += sc->sc_width) { + for (i = 0; i < wrbufsz; i += sc->sc_width) { /* Avoid writing unless we are actually changing bits */ if (!neederase) { @@ -724,7 +737,7 @@ cfi_write_block(struct cfi_softc *sc) switch (sc->sc_cmdset) { case CFI_VEND_INTEL_ECS: case CFI_VEND_INTEL_SCS: - cfi_write(sc, sc->sc_wrofs + i, CFI_BCS_PROGRAM); + cfi_write(sc, ofs + i, CFI_BCS_PROGRAM); break; case CFI_VEND_AMD_SCS: case CFI_VEND_AMD_ECS: @@ -734,40 +747,56 @@ cfi_write_block(struct cfi_softc *sc) switch (sc->sc_width) { case 1: bus_space_write_1(sc->sc_tag, sc->sc_handle, - sc->sc_wrofs + i, *(ptr.x8 + i)); + ofs + i, *(ptr.x8 + i)); break; case 2: bus_space_write_2(sc->sc_tag, sc->sc_handle, - sc->sc_wrofs + i, *(ptr.x16 + i / 2)); + ofs + i, *(ptr.x16 + i / 2)); break; case 4: bus_space_write_4(sc->sc_tag, sc->sc_handle, - sc->sc_wrofs + i, *(ptr.x32 + i / 4)); + ofs + i, *(ptr.x32 + i / 4)); break; } - + intr_restore(intr); - error = cfi_wait_ready(sc, sc->sc_wrofs, start, - CFI_TIMEOUT_WRITE); + error = cfi_wait_ready(sc, ofs, start, CFI_TIMEOUT_WRITE); if (error) - goto out; + return (error); } /* error is 0. */ + return (error); +} - out: - cfi_reset_default(sc); +int +cfi_write_block(struct cfi_softc *sc) +{ + int error, neederase = 0; + u_int i; - /* Relock Intel flash */ - switch (sc->sc_cmdset) { - case CFI_VEND_INTEL_ECS: - case CFI_VEND_INTEL_SCS: - cfi_write(sc, sc->sc_wrofs, CFI_INTEL_LBS); - cfi_write(sc, sc->sc_wrofs, CFI_INTEL_LB); - cfi_write(sc, sc->sc_wrofs, CFI_BCS_READ_ARRAY); - break; + cfi_unlock_flash(sc, sc->sc_wrofs); + + /* Check if an erase is required. */ + for (i = 0; i < sc->sc_wrbufsz; i++) + if ((sc->sc_wrbuf[i] & sc->sc_wrbufcpy[i]) != sc->sc_wrbuf[i]) { + neederase = 1; + break; + } + + if (neederase) { + error = cfi_erase_block(sc, sc->sc_wrofs); + if (error) + goto out; } + + error = cfi_program_block(sc, sc->sc_wrofs, sc->sc_wrbuf, + sc->sc_wrbufcpy, sc->sc_wrbufsz, neederase); + + out: + cfi_reset_default(sc); + cfi_relock_flash(sc, sc->sc_wrofs); return (error); } -- 2.12.3
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170616072122.17504-2-sebastian.huber>