Skip to content

Commit 432cdc2

Browse files
committed
lattice: added SPI Flash access support for ECP3 family
1 parent b76840b commit 432cdc2

File tree

2 files changed

+79
-53
lines changed

2 files changed

+79
-53
lines changed

doc/FPGAs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ Lattice:
183183
Model: LFE3-70E
184184
URL: https://www.latticesemi.com/Products/FPGAandCPLD/LatticeECP3
185185
Memory: OK
186-
Flash: TBD
186+
Flash: OK
187187

188188
- Description: ECP5
189189
Model:

src/lattice.cpp

Lines changed: 78 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -746,13 +746,19 @@ bool Lattice::prepare_flash_access()
746746
/* clear SRAM before SPI access */
747747
if (!clearSRAM())
748748
return false;
749-
/*IR = 0h3A, DR=0hFE,0h68. Enter RUNTESTIDLE.
750-
* thank @GregDavill
751-
* https://twitter.com/GregDavill/status/1251786406441086977
752-
*/
753-
_jtag->shiftIR(0x3A, 8, Jtag::EXIT1_IR);
754-
uint8_t tmp[2] = {0xFE, 0x68};
755-
_jtag->shiftDR(tmp, NULL, 16);
749+
if (_fpga_family == ECP3_FAMILY) {
750+
if (!wr_rd(0x3A, 0, 0, 0, 0, false))
751+
return false;
752+
_jtag->set_state(Jtag::RUN_TEST_IDLE);
753+
} else {
754+
/*IR = 0h3A, DR=0hFE,0h68. Enter RUNTESTIDLE.
755+
* thank @GregDavill
756+
* https://twitter.com/GregDavill/status/1251786406441086977
757+
*/
758+
_jtag->shiftIR(0x3A, 8, Jtag::EXIT1_IR);
759+
uint8_t tmp[2] = {0xFE, 0x68};
760+
_jtag->shiftDR(tmp, NULL, 16);
761+
}
756762
return true;
757763
}
758764

@@ -763,50 +769,55 @@ bool Lattice::post_flash_access()
763769
printInfo("Skip resetting device");
764770
return true;
765771
}
766-
/* ISC REFRESH 0x79 */
767-
if (loadConfiguration() == false) {
768-
/* when flash is blank status displays failure:
769-
* try to check flash first sector
770-
*/
771-
_skip_reset = true; // avoid infinite loop
772-
/* read flash 0 -> 255 */
773-
uint8_t buffer[256];
774-
ret = SPIInterface::read(buffer, 0, 256);
775-
loadConfiguration(); // reset again
776-
777-
/* read ok? check if everything == 0xff */
778-
if (ret) {
779-
for (int i = 0; i < 256; i++) {
780-
/* not blank: fail */
781-
if (buffer[i] != 0xFF) {
782-
ret = false;
783-
break;
772+
if (_fpga_family == ECP3_FAMILY) {
773+
_jtag->shiftIR(0xFF, 8, Jtag::RUN_TEST_IDLE);
774+
_jtag->shiftIR(0x23, 8, Jtag::RUN_TEST_IDLE);
775+
} else {
776+
/* ISC REFRESH 0x79 */
777+
if (loadConfiguration() == false) {
778+
/* when flash is blank status displays failure:
779+
* try to check flash first sector
780+
*/
781+
_skip_reset = true; // avoid infinite loop
782+
/* read flash 0 -> 255 */
783+
uint8_t buffer[256];
784+
ret = SPIInterface::read(buffer, 0, 256);
785+
loadConfiguration(); // reset again
786+
787+
/* read ok? check if everything == 0xff */
788+
if (ret) {
789+
for (int i = 0; i < 256; i++) {
790+
/* not blank: fail */
791+
if (buffer[i] != 0xFF) {
792+
ret = false;
793+
break;
794+
}
784795
}
796+
/* to add a note */
797+
flash_blank = true;
785798
}
786-
/* to add a note */
787-
flash_blank = true;
788799
}
789-
}
790800

791-
printInfo("Refresh: ", false);
792-
if (!ret) {
793-
printError("FAIL");
794-
displayReadReg(readStatusReg());
795-
return false;
796-
} else {
797-
printSuccess("DONE");
798-
if (flash_blank)
799-
printWarn("Flash is blank");
800-
}
801+
printInfo("Refresh: ", false);
802+
if (!ret) {
803+
printError("FAIL");
804+
displayReadReg(readStatusReg());
805+
return false;
806+
} else {
807+
printSuccess("DONE");
808+
if (flash_blank)
809+
printWarn("Flash is blank");
810+
}
801811

802-
/* bypass */
803-
wr_rd(0xff, NULL, 0, NULL, 0);
804-
_jtag->go_test_logic_reset();
812+
/* bypass */
813+
wr_rd(0xff, NULL, 0, NULL, 0);
814+
_jtag->go_test_logic_reset();
815+
}
805816
return true;
806817
}
807818
void Lattice::reset()
808819
{
809-
if (_fpga_family == ECP5_FAMILY)
820+
if (_fpga_family == ECP5_FAMILY || _fpga_family == ECP3_FAMILY)
810821
post_flash_access();
811822
else
812823
printError("Lattice Reset only tested on ECP5 Family.");
@@ -1670,10 +1681,14 @@ uint16_t Lattice::getUFMStartPageFromJEDEC(JedParser *_jed, int id)
16701681

16711682
int Lattice::spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, uint32_t len)
16721683
{
1673-
int xfer_len = len + 1;
1684+
const uint32_t xfer_len = len + 1 + ((rx != NULL) && ((_fpga_family == ECP3_FAMILY)) ? 1 : 0);
1685+
const uint32_t xfer_bit_len = (len + 1) * 8 + ((rx != NULL) && ((_fpga_family == ECP3_FAMILY)) ? 1 : 0);
16741686
uint8_t jtx[xfer_len];
16751687
uint8_t jrx[xfer_len];
16761688

1689+
memset(jrx, 0, xfer_len);
1690+
memset(jtx, 0, xfer_len);
1691+
16771692
jtx[0] = LatticeBitParser::reverseByte(cmd);
16781693

16791694
if (tx) {
@@ -1685,11 +1700,18 @@ int Lattice::spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, uint32_t len)
16851700
* in the same time store each byte
16861701
* to next
16871702
*/
1688-
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*xfer_len);
1703+
_jtag->shiftDR(jtx, (!rx)? NULL: jrx, xfer_bit_len);
16891704

1690-
if (rx != NULL) {
1691-
for (uint32_t i=0; i < len; i++)
1692-
rx[i] = LatticeBitParser::reverseByte(jrx[i+1]);
1705+
if (rx) {
1706+
if (_fpga_family == ECP3_FAMILY) {
1707+
for (uint32_t i = 0; i < len; ++i) {
1708+
const uint8_t tmp = LatticeBitParser::reverseByte((jrx[i+1] >> 1) & 0x7f);
1709+
rx[i] = tmp | (jrx[i + 2] & 0x01);
1710+
}
1711+
} else {
1712+
for (uint32_t i=0; i < len; i++)
1713+
rx[i] = LatticeBitParser::reverseByte(jrx[i+1]);
1714+
}
16931715
}
16941716
return 0;
16951717
}
@@ -1725,11 +1747,12 @@ int Lattice::spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len)
17251747
int Lattice::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
17261748
uint32_t timeout, bool verbose)
17271749
{
1728-
uint8_t rx;
1750+
uint8_t rx[2];
17291751
uint8_t dummy[2] = {0xff};
17301752
uint8_t tmp;
17311753
uint8_t tx = LatticeBitParser::reverseByte(cmd);
17321754
uint32_t count = 0;
1755+
uint32_t nb_byte = (_fpga_family == ECP3_FAMILY) ? 2 : 1;
17331756

17341757
/* CS is low until state goes to EXIT1_IR
17351758
* so manually move to state machine to stay is this
@@ -1738,19 +1761,22 @@ int Lattice::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
17381761
_jtag->shiftDR(&tx, NULL, 8, Jtag::SHIFT_DR);
17391762

17401763
do {
1741-
_jtag->shiftDR(dummy, &rx, 8, Jtag::SHIFT_DR);
1742-
tmp = (LatticeBitParser::reverseByte(rx));
1764+
_jtag->shiftDR(dummy, rx, 8 * nb_byte, Jtag::SHIFT_DR);
1765+
if (_fpga_family == ECP3_FAMILY)
1766+
tmp = LatticeBitParser::reverseByte(rx[0] >> 1) | (rx[1] & 0x01);
1767+
else
1768+
tmp = (LatticeBitParser::reverseByte(rx[0]));
17431769
count++;
17441770
if (count == timeout){
1745-
printf("timeout: %x %x %u\n", tmp, rx, count);
1771+
printf("timeout: %x %x %u\n", tmp, rx[0], count);
17461772
break;
17471773
}
17481774

17491775
if (verbose) {
17501776
printf("%x %x %x %u\n", tmp, mask, cond, count);
17511777
}
17521778
} while ((tmp & mask) != cond);
1753-
_jtag->shiftDR(dummy, &rx, 8, Jtag::RUN_TEST_IDLE);
1779+
_jtag->shiftDR(dummy, rx, 8, Jtag::RUN_TEST_IDLE);
17541780
if (count == timeout) {
17551781
printf("%x\n", tmp);
17561782
std::cout << "wait: Error" << std::endl;

0 commit comments

Comments
 (0)