[prev in list] [next in list] [prev in thread] [next in thread]
List: freebsd-hackers
Subject: [PATCH 2/2] cfi: Refactor cfi_write_block()
From: Sebastian Huber <sebastian.huber () embedded-brains ! de>
Date: 2017-06-16 7:21:22
Message-ID: 20170616072122.17504-2-sebastian.huber () embedded-brains ! de
[Download RAW message or body]
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
_______________________________________________
freebsd-hackers@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic