Skip to content

Commit

Permalink
Add support for flashing UFM on MachXO2 using JEDEC file. (#339)
Browse files Browse the repository at this point in the history
* Add support for flashing UFM on MachXO2 using JEDEC file.

* Use a better guard value for getUFMStartPageFromJEDEC.

* Fix if-else style in  getUFMStartPageFromJEDEC.
  • Loading branch information
cr1901 authored Apr 30, 2023
1 parent 873de96 commit 0db174e
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
67 changes: 64 additions & 3 deletions src/lattice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ using namespace std;
#define ISC_DISABLE 0x26 /* ISC_DISABLE */
#define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */
#define FLASH_ERASE 0x0E /* ISC_ERASE */
/* Flash areas as defined for Lattice MachXO3L/LF */
/* Flash areas as defined for Lattice MachXO2,3L/LF */
# define FLASH_ERASE_UFM (1<<3)
# define FLASH_ERASE_CFG (1<<2)
# define FLASH_ERASE_FEATURE (1<<1)
Expand Down Expand Up @@ -399,6 +399,7 @@ bool Lattice::program_mem()
bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
{
uint64_t featuresRow;
uint16_t ufm_start = 0;
uint16_t feabits;
uint8_t eraseMode = 0;
vector<string> ufm_data, cfg_data, ebr_data;
Expand All @@ -425,6 +426,16 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
if (note == "TAG DATA") {
eraseMode |= FLASH_ERASE_UFM;
ufm_data = _jed->data_for_section(i);
ufm_start = getUFMStartPageFromJEDEC(_jed, i);

if (_verbose)
printf("UFM init detected in JEDEC file");

if(ufm_start > 2045) {
printError("UFM section detected in JEDEC file, but "
"calculated flash start address was out of bounds");
return false;
}
} else if (note == "END CONFIG DATA") {
continue;
} else if (note == "EBR_INIT DATA") {
Expand All @@ -444,7 +455,7 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
feabits = 0x460;
}

eraseMode = FLASH_ERASE_CFG;
eraseMode |= FLASH_ERASE_CFG;
if (featuresRow != readFeaturesRow() || feabits != readFeabits())
eraseMode |= FLASH_ERASE_FEATURE;

Expand Down Expand Up @@ -477,6 +488,24 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
return false;
}

if ((eraseMode & FLASH_ERASE_UFM) != 0) {
/* LSC_WRITE_ADDRESS */
uint8_t tx[4] = {
ufm_start & 0xff,
(ufm_start >> 8) & 0xff,
0,
0x40
};

wr_rd(LSC_WRITE_ADDRESS, tx, 4, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000);

/* Same command to program CFG flash works for UFM. */
if (false == flashProg(0, "UFM", ufm_data))
return false;
}

/* missing usercode update */

/* LSC_INIT_ADDRESS */
Expand Down Expand Up @@ -831,7 +860,7 @@ bool Lattice::checkID()
{
printf("\n");
printf("check ID\n");
uint8_t tx[4];
uint8_t tx[4] = { 0 };
wr_rd(0xE2, tx, 4, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000);
Expand Down Expand Up @@ -1253,6 +1282,38 @@ bool Lattice::loadConfiguration()
return true;
}

uint16_t Lattice::getUFMStartPageFromJEDEC(JedParser *_jed, int id)
{
/* In general, Lattice tools try to fill UFM from the highest
page to lowest. JEDEC files will give a starting bit offset. */
uint32_t bit_offset = _jed->offset_for_section(id);
/* Convert to starting page, which seems to be one more than the number
of Configuration Flash pages, based on looking at Diamond-generated
JEDECs. */
uint16_t raw_page_offset = bit_offset / 128;

/* Raw page offsets won't overlap- see Lattice TN-02155, page 49. So we
can uniquely determine which part type we're targeting from the UFM start
addres.
TODO: In any case, JEDEC files don't carry part information. Verify against
IDCODE read previously? */

if(raw_page_offset > 9211) {
return raw_page_offset - 9211 - 1; // 7000
} else if(raw_page_offset > 5758) {
return raw_page_offset - 5758 - 1; // 4000, 2000U
} else if(raw_page_offset > 3198) {
return raw_page_offset - 3198 - 1; // 2000, 1200U
} else if(raw_page_offset > 2175) {
return raw_page_offset - 2175 - 1; // 1200, 640U
} else if(raw_page_offset > 1151) {
return raw_page_offset - 1151 - 1; // 640
} else {
// 256- We should bail if we get here! No UFM!
return 0xffff;
}
}

/* ------------------ */
/* SPI implementation */
/* ------------------ */
Expand Down
1 change: 1 addition & 0 deletions src/lattice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class Lattice: public Device, SPIInterface {
bool writeFeabits(uint16_t feabits, bool verify);
bool writeProgramDone();
bool loadConfiguration();
uint16_t getUFMStartPageFromJEDEC(JedParser *_jed, int id);

/* test */
bool checkID();
Expand Down

0 comments on commit 0db174e

Please sign in to comment.