QSPIFBlockDevice: Add quirk to ignore overlaying sectors on S25FS512S

The entire flash chip S25FS512S consists of uniform 256KB sectors.
Additionally, it has three configurations:
* 0x01: Eight 4KB sectors (32KB in total) overlaying the start of
the first 256KB sector
* 0x03: Eight 4KB sectors (32KB in total) overlaying the end of the
last 256KB sector
* 0x05: No overlaying sectors

The active configuration is determined from bit fields of two
registers, CR1NV and CR3NV.

Mbed OS does not currently support partially overlaying sectors,
meaning that with eight 4KB sectors overlay a 256KB sectors, the
remaining 224KB (== 256KB - 8 * 4KB) of the big sector can't be
correctly handled. Supporting such scenario would involve a large
amount of rewriting in Mbed OS's BlockDevice, SFDP and their tests,
and may increase the code size.

So, this commit applies a quirk to always report configuration 0x05
(no overlaying sectors). Even if 0x01 or 0x03 is the real configuration,
they are compatible with the 0x05 configuration because 256KB sectors
exist in all cases.

Note: This quirk does *not* change actual configurations on hardware,
because registers CR1NV and CR3NV are one-time configurable (OTP) -
each bit field has a factory value of 0 and can be changed to 1 by the
user but not back to 0. So QSPIFBlockDevice avoids changing them.
pull/14989/head
Lingkai Dong 2021-08-10 10:01:59 +01:00
parent 6032671b41
commit 23a79ef459
1 changed files with 11 additions and 0 deletions

View File

@ -1109,6 +1109,13 @@ int QSPIFBlockDevice::_handle_vendor_quirks()
// * The SFDP table expects the register bitfield CR3NV[1] to be 1
// but its actual value on the hardware is 0. In order for SFDP parsing
// to work, the quirk reports CR3NV[1] as 1.
// * All three possible configurations support 256KB sectors across
// the entire chip. But when CR3NV[3] is 0, eight 4KB sectors overlay
// either the first 32KB or the last 32KB of the chip, whereas when
// CR3NV[3] is 1 there are no overlaying 4KB sectors. Mbed OS can't
// handle this type of overlay, so the quirk reports CR3NV[3] as 1 to
// let the code treat the chip as if it has no overlay. (Also CR1NV[2]
// is required to be 0 when CR3NV[3] is 1.)
_S25FS512S_quirk = true;
}
break;
@ -1483,12 +1490,16 @@ int QSPIFBlockDevice::_qspi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::s
}
// Handle S25FS512S quirk.
const mbed::bd_addr_t S25FS512S_CR1NV = 0x2;
const mbed::bd_addr_t S25FS512S_CR3NV = 0x4;
if (_S25FS512S_quirk) {
if (addr == S25FS512S_CR3NV) {
// If we reach here, rx_buffer is guaranteed to be non-null
// because it's been checked by _qspi.read() above.
static_cast<uint8_t *>(rx_buffer)[0] |= (1 << 1);
static_cast<uint8_t *>(rx_buffer)[0] |= (1 << 3);
} else if (addr == S25FS512S_CR1NV) {
static_cast<uint8_t *>(rx_buffer)[0] &= ~(1 << 2);
}
}