Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for flashing UFM on MachXO2 using JEDEC file. #339

Merged
merged 3 commits into from
Apr 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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