chromeec: ec_mec: Fix misaligned data access
Long auto-increment access cannot be used when our initial address is misaligned or when our terminal address is misaligned on write operations. BUG=chrome-os-partner:38224 TEST=Verify host command functionality on cyan. BRANCH=None Change-Id: Ieba0e8e05dabd44a28c63d5d56a2a634c2d349bf Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: a7237c8df027ae70a38478846ff3d5ce97543ff1 Original-Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Original-Change-Id: Id709ca92cc386f9ea5b2a1139733961e1bc59354 Original-Reviewed-on: https://chromium-review.googlesource.com/266653 Original-Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/9987 Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
8603680c4a
commit
16fb9b9f81
|
@ -76,12 +76,22 @@ void mec_io_bytes(int write, u16 port, unsigned int length, u8 *buf, u8 *csum)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int io_addr;
|
int io_addr;
|
||||||
|
u8 access_mode, new_access_mode;
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Long access cannot be used on misaligned data since reading B0 loads
|
||||||
|
* the data register and writing B3 flushes it.
|
||||||
|
*/
|
||||||
|
if (port & 0x3)
|
||||||
|
access_mode = ACCESS_TYPE_BYTE;
|
||||||
|
else
|
||||||
|
access_mode = ACCESS_TYPE_LONG_AUTO_INCREMENT;
|
||||||
|
|
||||||
/* Initialize I/O at desired address */
|
/* Initialize I/O at desired address */
|
||||||
mec_emi_write_address(port, ACCESS_TYPE_LONG_AUTO_INCREMENT);
|
mec_emi_write_address(port, access_mode);
|
||||||
|
|
||||||
/* Skip bytes in case of misaligned port */
|
/* Skip bytes in case of misaligned port */
|
||||||
io_addr = MEC_EMI_EC_DATA_B0 + (port & 0x3);
|
io_addr = MEC_EMI_EC_DATA_B0 + (port & 0x3);
|
||||||
|
@ -94,11 +104,26 @@ void mec_io_bytes(int write, u16 port, unsigned int length, u8 *buf, u8 *csum)
|
||||||
if (csum)
|
if (csum)
|
||||||
*csum += buf[i];
|
*csum += buf[i];
|
||||||
|
|
||||||
|
port++;
|
||||||
/* Extra bounds check in case of misaligned length */
|
/* Extra bounds check in case of misaligned length */
|
||||||
if (++i == length)
|
if (++i == length)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use long auto-increment access except for misaligned write,
|
||||||
|
* since writing B3 triggers the flush.
|
||||||
|
*/
|
||||||
|
if (length - i < 4 && write)
|
||||||
|
new_access_mode = ACCESS_TYPE_BYTE;
|
||||||
|
else
|
||||||
|
new_access_mode = ACCESS_TYPE_LONG_AUTO_INCREMENT;
|
||||||
|
if (new_access_mode != access_mode ||
|
||||||
|
access_mode != ACCESS_TYPE_LONG_AUTO_INCREMENT) {
|
||||||
|
access_mode = new_access_mode;
|
||||||
|
mec_emi_write_address(port, access_mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* Access [B0, B3] on each loop pass */
|
/* Access [B0, B3] on each loop pass */
|
||||||
io_addr = MEC_EMI_EC_DATA_B0;
|
io_addr = MEC_EMI_EC_DATA_B0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue