xilinx: adding zynqmp support and a method to init this family of devices

This commit is contained in:
Gwenhael Goavec-Merou 2022-01-13 08:41:38 +01:00
parent dddee79f53
commit f44f92ea4b
2 changed files with 73 additions and 0 deletions

View File

@ -58,6 +58,10 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
_fpga_family = SPARTAN7_FAMILY;
} else if (family == "zynq") {
_fpga_family = ZYNQ_FAMILY;
} else if (family.substr(0, 6) == "zynqmp") {
if (!zynqmp_init(family))
throw std::runtime_error("Error with ZynqMP init");
_fpga_family = ZYNQMP_FAMILY;
} else if (family == "kintex7") {
_fpga_family = KINTEX_FAMILY;
} else if (family == "spartan3") {
@ -96,6 +100,67 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
}
Xilinx::~Xilinx() {}
bool Xilinx::zynqmp_init(const std::string &family)
{
/* by default, at powering a zynqmp has
* PL TAP and ARM DAP disabled
* at this time only PS TAB and a dummy are seen
* So first step is to enable PL and ARM
*/
if (family == "zynqmp_cfgn") {
/* PS TAP is the first device with 0xfffffe idcode */
_jtag->device_select(0);
/* send 0x03 into JTAG_CTRL register */
uint16_t ircode = 0x824;
_jtag->shiftIR(ircode & 0xff, 8, Jtag::SHIFT_IR);
_jtag->shiftIR((ircode >> 9) & 0x3f, 4);
uint8_t instr[4] = {0x3, 0, 0, 0};
_jtag->shiftDR(instr, NULL, 32);
/* synchronize everything by moving to TLR */
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
_jtag->toggleClk(10);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(100);
/* force again JTAG chain detection */
_jtag->detectChain(5);
}
/* check if the chain is correctly configured:
* 2 devices
* PL at position 0
* ARM at position 1
*/
char mess[256];
std::vector<int> listDev = _jtag->get_devices_list();
if (listDev.size() != 2) {
snprintf(mess, sizeof(mess), "ZynqMP error: wrong"
" JTAG length: %zu instead of 2\n",
listDev.size());
printError(mess);
return false;
}
if (fpga_list[listDev[0]].family != "zynqmp") {
snprintf(mess, sizeof(mess), "ZynqMP error: first device"
" is not the PL TAP -> 0x%08x\n",
listDev[0]);
printError(mess);
return false;
}
if (listDev[1] != 0x5ba00477) {
snprintf(mess, sizeof(mess), "ZynqMP error: second device"
" is not the ARM DAP cortex A53 -> 0x%08x\n",
listDev[1]);
printError(mess);
return false;
}
_jtag->insert_first(0xdeadbeef, 6);
_jtag->device_select(1);
return true;
}
#define USER1 0x02
#define CFG_IN 0x05
#define USERCODE 0x08

View File

@ -140,12 +140,20 @@ class Xilinx: public Device, SPIInterface {
ARTIX_FAMILY,
KINTEX_FAMILY,
ZYNQ_FAMILY,
ZYNQMP_FAMILY,
XCF_FAMILY,
UNKNOWN_FAMILY = 999
};
xilinx_family_t _fpga_family; /**< used to store current family */
/*!
* \brief xilinx ZynqMP Ultrascale+ specific initialization
* \param[in] family name
* \return true if device has been correctly initilized
*/
bool zynqmp_init(const std::string &family);
/*!
* \brief with xilinx devices SPI flash direct access is not possible
* so a bridge must be loaded in RAM to access flash