From 64c94a20c8030479d4e8553bbfed7382b16b8f84 Mon Sep 17 00:00:00 2001 From: David Mc Andrew Date: Wed, 30 May 2012 17:29:10 +0100 Subject: [PATCH] Xilinx: MicroBlaze: Add Kintex 7 Bitstream Boot Command This patch adds a command for loading bitstreams The following definitions are used: Signed-off-by: David Mc Andrew --- arch/microblaze/include/asm/icap.h | 279 +++++++++++++++++++++++++++++ arch/microblaze/lib/bootm.c | 63 +++++++ 2 files changed, 342 insertions(+) create mode 100755 arch/microblaze/include/asm/icap.h mode change 100644 => 100755 arch/microblaze/lib/bootm.c diff --git a/arch/microblaze/include/asm/icap.h b/arch/microblaze/include/asm/icap.h new file mode 100755 index 00000000000..8d4fe790ce8 --- /dev/null +++ b/arch/microblaze/include/asm/icap.h @@ -0,0 +1,279 @@ +#include + +#define XHwIcap_In32 readl + +#define XHwIcap_Out32(a,b) writel(b,a) /* switch address & data */ + +/* Packet Types */ +#define XHI_SYNC_PACKET 0xAA995566 +#define XHI_DUMMY_PACKET 0xFFFFFFFF +#define XHI_DEVICE_ID_READ 0x28018001 +#define XHI_NOOP_PACKET 0x20000000 + +/* Command types */ +#define XHI_TYPE_1 1 + +/* Command Direction */ +#define XHI_OP_READ 1 + +/* Register Programming Offsets */ +#define XHI_TYPE_SHIFT 29 +#define XHI_REGISTER_SHIFT 13 +#define XHI_OP_SHIFT 27 + +/* Register Offsets */ +#define XHI_WBSTAR 16 + +/* Register offsets for the XHwIcap device. */ +#define XHI_GIER_OFFSET 0x1C /**< Device Global Interrupt Enable Reg */ +#define XHI_IPISR_OFFSET 0x20 /**< Interrupt Status Register */ +#define XHI_IPIER_OFFSET 0x28 /**< Interrupt Enable Register */ +#define XHI_WF_OFFSET 0x100 /**< Write FIFO */ +#define XHI_RF_OFFSET 0x104 /**< Read FIFO */ +#define XHI_SZ_OFFSET 0x108 /**< Size Register */ +#define XHI_CR_OFFSET 0x10C /**< Control Register */ +#define XHI_SR_OFFSET 0x110 /**< Status Register */ +#define XHI_WFV_OFFSET 0x114 /**< Write FIFO Vacancy Register */ +#define XHI_RFO_OFFSET 0x118 /**< Read FIFO Occupancy Register */ + +/* Control Register Contents */ +#define XHI_CR_READ_MASK 0x00000002 /**< Read from ICAP to FIFO */ +#define XHI_CR_WRITE_MASK 0x00000001 /**< Write from FIFO to ICAP */ + +/* Status Register Contents */ +#define XHI_SR_DONE_MASK 0x00000001 /**< Done bit Mask */ + +/* Number of times to poll the Status Register */ +#define XHI_MAX_RETRIES 1000 + +/* Program Command */ +#define XHI_CMD_IPROG 15 + + +/****************************************************************************/ +/** +* +* Read from the specified HwIcap device register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to select the specific register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XHwIcap_ReadReg(u32 BaseAddress, u32 RegOffset); +* +******************************************************************************/ +#define XHwIcap_ReadReg(BaseAddress, RegOffset) \ + XHwIcap_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* +* Write to the specified HwIcap device register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to select the specific register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XHwIcap_WriteReg(u32 BaseAddress, u32 RegOffset, +* u32 RegisterValue); +******************************************************************************/ +#define XHwIcap_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XHwIcap_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/****************************************************************************/ +/** +* +* Write data to the Write FIFO. +* +* @param BaseAddress contains the base address of the device. +* @param Data is the 32-bit value to be written to the FIFO. +* +* @return None. +* +* @note C-style Signature: +* void XHwIcap_FifoWrite(u32 BaseAddress, u32 Data); +* +*****************************************************************************/ +#define XHwIcap_FifoWrite(BaseAddress,Data) \ + (XHwIcap_WriteReg(BaseAddress, XHI_WF_OFFSET, (Data))) + +/****************************************************************************/ +/** +* +* Read data from the Read FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return The 32-bit Data read from the FIFO. +* +* @note C-style Signature: +* u32 XHwIcap_FifoRead(u32 BaseAddress); +* +*****************************************************************************/ +#define XHwIcap_FifoRead(BaseAddress) \ +(XHwIcap_ReadReg(BaseAddress, XHI_RF_OFFSET)) + +/****************************************************************************/ +/** +* +* Get the contents of the Control register. +* +* @param BaseAddress contains the base address of the device. +* +* @return A 32-bit value representing the contents of the Control +* register. +* +* @note u32 XHwIcap_GetControlReg(u32 BaseAddress); +* +*****************************************************************************/ +#define XHwIcap_GetControlReg(BaseAddress) \ + (XHwIcap_ReadReg(BaseAddress, XHI_CR_OFFSET)) + + +/****************************************************************************/ +/** +* +* Set the Control Register to initiate a configuration (write) to the device. +* +* @param BaseAddress contains the base address of the device. +* +* @return None. +* +* @note C-style Signature: +* void XHwIcap_StartConfig(u32 BaseAddress); +* +*****************************************************************************/ +#define XHwIcap_StartConfig(BaseAddress) \ + (XHwIcap_WriteReg(BaseAddress, XHI_CR_OFFSET, (XHwIcap_GetControlReg(BaseAddress) & \ + (~ XHI_CR_READ_MASK)) | XHI_CR_WRITE_MASK)) + +/******************************************************************************/ +/** +* +* This macro returns the vacancy of the Write FIFO. This indicates the +* number of words that can be written to the Write FIFO before it becomes +* full. +* +* @param BaseAddress contains the base address of the device. +* +* @return The contents read from the Write FIFO Vacancy Register. +* +* @note C-Style signature: +* u32 XHwIcap_GetWrFifoVacancy(u32 BaseAddress) +* +******************************************************************************/ +#define XHwIcap_GetWrFifoVacancy(BaseAddress) \ + XHwIcap_ReadReg(BaseAddress, XHI_WFV_OFFSET) + +/******************************************************************************/ +/** +* +* This macro returns the occupancy of the Read FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return The contents read from the Read FIFO Occupancy Register. +* +* @note C-Style signature: +* u32 XHwIcap_GetRdFifoOccupancy(u32 BaseAddress) +* +******************************************************************************/ +#define XHwIcap_GetRdFifoOccupancy(BaseAddress) \ + XHwIcap_ReadReg(BaseAddress, XHI_RFO_OFFSET) + +/****************************************************************************/ +/** +* +* Get the contents of the status register. +* +* @param BaseAddress contains the base address of the device. +* +* @return A 32-bit value representing the contents of the status register. +* +* @note u32 XHwIcap_GetStatusReg(u32 BaseAddress); +* +*****************************************************************************/ +#define XHwIcap_GetStatusReg(BaseAddress) \ +(XHwIcap_ReadReg(BaseAddress, XHI_SR_OFFSET)) + +/****************************************************************************/ +/** +* +* This macro checks if the last Read/Write to the ICAP device in the FPGA +* is completed. +* +* @param BaseAddress contains the base address of the device. +* +* @return +* - 1 if the last Read/Write(Config) to the ICAP is NOT +* completed. +* - 0 if the Read/Write(Config) to the ICAP is completed.. +* +* @note C-Style signature: +* int XHwIcap_IsDeviceBusy(u32 BaseAddress); +* +*****************************************************************************/ +#define XHwIcap_IsDeviceBusy(BaseAddress) \ + ((XHwIcap_GetStatusReg(BaseAddress) & XHI_SR_DONE_MASK) ? 0 : 1) + +/****************************************************************************/ +/** +* +* Set the number of words to be read from the Icap in the Size register. +* +* The Size Register holds the number of 32 bit words to transfer from the +* the Icap to the Read FIFO of the HwIcap device. +* +* @param BaseAddress contains the base address of the device. +* @param Data is the size in words. +* +* @return None. +* +* @note C-style Signature: +* void XHwIcap_SetSizeReg(u32 BaseAddress, u32 Data); +* +*****************************************************************************/ +#define XHwIcap_SetSizeReg(BaseAddress, Data) \ + (XHwIcap_WriteReg(BaseAddress, XHI_SZ_OFFSET, (Data))) + +/****************************************************************************/ +/** +* +* Set the Control Register to initiate a ReadBack from the device. +* +* @param BaseAddress contains the base address of the device. +* +* @return None. +* +* @note C-style Signature: +* void XHwIcap_StartReadBack(u32 BaseAddress); +* +*****************************************************************************/ +#define XHwIcap_StartReadBack(BaseAddress) \ + (XHwIcap_WriteReg(BaseAddress, XHI_CR_OFFSET, (XHwIcap_GetControlReg(BaseAddress) & \ + (~ XHI_CR_WRITE_MASK)) | XHI_CR_READ_MASK)) + +/****************************************************************************/ +/** +* +* Generates a Type 1 packet header that reads back the requested Configuration +* register. +* +* @param Register is the address of the register to be read back. +* +* @return Type 1 packet header to read the specified register +* +* @note None. +* +*****************************************************************************/ +#define XHwIcap_Type1Read(Register) \ + ( (XHI_TYPE_1 << XHI_TYPE_SHIFT) | (Register << XHI_REGISTER_SHIFT) | \ + (XHI_OP_READ << XHI_OP_SHIFT) ) + diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c old mode 100644 new mode 100755 index 95cee509d25..491241bc636 --- a/arch/microblaze/lib/bootm.c +++ b/arch/microblaze/lib/bootm.c @@ -30,6 +30,10 @@ #include #include +#if defined(CONFIG_CMD_BOOTB) +#include +#endif + DECLARE_GLOBAL_DATA_PTR; int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) @@ -88,3 +92,62 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima return 1; } + +#if defined(CONFIG_CMD_BOOTB) +int do_bootb_kintex7(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u32 FrameBuffer[8]; + u32 BootAddress = simple_strtoul(argv[1], NULL, 16); + u32 Index = 0; + u32 Count; + + if (argc < 2) + return -1; + + if ((BootAddress < CONFIG_SYS_FLASH_BASE) || (BootAddress > (CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_SIZE))) + { + return -1; + } + + /* + * Create the data to be written to the ICAP. + */ + FrameBuffer[Index++] = XHI_DUMMY_PACKET; + FrameBuffer[Index++] = XHI_SYNC_PACKET; + FrameBuffer[Index++] = XHI_NOOP_PACKET; + FrameBuffer[Index++] = 0x30020001; /* Type 1 write to WBSTAR */ + FrameBuffer[Index++] = BootAddress; + FrameBuffer[Index++] = 0x30008001; /* Type 1 Write to CMD */ + FrameBuffer[Index++] = XHI_CMD_IPROG; + FrameBuffer[Index++] = XHI_NOOP_PACKET; + + /* + * Fill the FIFO with as many words as it will take (or as many as we have to send). + */ + while(Index > XHwIcap_GetWrFifoVacancy(HWICAP_BASEADDR)); + for (Count = 0; Count < Index; Count++) + { + XHwIcap_FifoWrite(HWICAP_BASEADDR, FrameBuffer[Count]); + } + + /* + * Start the transfer of the data from the FIFO to the ICAP device. + */ + XHwIcap_StartConfig(HWICAP_BASEADDR); + + while ((XHwIcap_ReadReg(HWICAP_BASEADDR,XHI_CR_OFFSET)) & XHI_CR_WRITE_MASK); + + while (XHwIcap_IsDeviceBusy(HWICAP_BASEADDR) != 0); + while (XHwIcap_ReadReg(HWICAP_BASEADDR, XHI_CR_OFFSET) & XHI_CR_WRITE_MASK); + + /* The code should never get here sice the FPGA should reset */ + return -1; +} + +U_BOOT_CMD( + bootb, 2, 1, do_bootb_kintex7, + "reprogram the fpga with a new image", + "
- Program the FPGA with the data starting at the given address" +); + +#endif -- 2.47.3