arm: socfpga: scan: Add code to get FPGA ID
authorDinh Nguyen <dinguyen@opensource.altera.com>
Fri, 31 Jul 2015 16:06:50 +0000 (11:06 -0500)
committerMarek Vasut <marex@denx.de>
Sat, 8 Aug 2015 12:14:30 +0000 (14:14 +0200)
Add code to get the FPGA type for Altera's SoCFPGA family of FPGA. The code
uses the scan manager to send jtag pulses that will return the FPGA ID.

Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
arch/arm/mach-socfpga/include/mach/scan_manager.h
arch/arm/mach-socfpga/scan_manager.c

index 3b55e370f2f4d1077a4f03ccc8016698e23a6d02..5ca6843557577b691f677ab28e744eb4cd6822ed 100644 (file)
@@ -18,6 +18,7 @@ struct socfpga_scan_manager {
 };
 
 int scan_mgr_configure_iocsr(void);
+u32 scan_mgr_get_fpga_id(void);
 int iocsr_get_config_table(const unsigned int chain_id,
                           const unsigned long **table,
                           unsigned int *table_len);
index e3c4684989832672c2327a95704f4817e2b357d8..566b33f2b6a0e92d37e5773ba9527f3ae22760f9 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/io.h>
 #include <asm/arch/freeze_controller.h>
 #include <asm/arch/scan_manager.h>
+#include <asm/arch/system_manager.h>
 
 /*
  * Maximum polling loop to wait for IO scan chain engine becomes idle
@@ -33,6 +34,8 @@ static const struct socfpga_scan_manager *scan_manager_base =
                (void *)(SOCFPGA_SCANMGR_ADDRESS);
 static const struct socfpga_freeze_controller *freeze_controller_base =
                (void *)(SOCFPGA_SYSMGR_ADDRESS + SYSMGR_FRZCTRL_ADDRESS);
+static struct socfpga_system_manager *sys_mgr_base =
+       (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
 
 /**
  * scan_chain_engine_is_idle() - Check if the JTAG scan chain is idle
@@ -205,3 +208,55 @@ int scan_mgr_configure_iocsr(void)
        status |= scan_mgr_io_scan_chain_prg(3);
        return status;
 }
+
+/**
+ * scan_mgr_get_fpga_id() - Obtain FPGA JTAG ID
+ *
+ * This function obtains JTAG ID from the FPGA TAP controller.
+ */
+u32 scan_mgr_get_fpga_id(void)
+{
+       const unsigned long data = 0;
+       u32 id = 0xffffffff;
+       int ret;
+
+       /* Enable HPS to talk to JTAG in the FPGA through the System Manager */
+       writel(0x1, &sys_mgr_base->scanmgrgrp_ctrl);
+
+       /* Enable port 7 */
+       writel(0x80, &scan_manager_base->en);
+       /* write to CSW to make s2f_ntrst reset */
+       writel(0x02, &scan_manager_base->stat);
+
+       /* Add a pause */
+       mdelay(1);
+
+       /* write 0x00 to CSW to clear the s2f_ntrst */
+       writel(0, &scan_manager_base->stat);
+
+       /*
+        * Go to Test-Logic-Reset state.
+        * This sets TAP controller into IDCODE mode.
+        */
+       scan_mgr_jtag_io(JTAG_BP_INSN | JTAG_BP_TMS, 0x1f | (1 << 5), 0x0);
+
+       /* Go to Run-Test/Idle -> DR-Scan -> Capture-DR -> Shift-DR state. */
+       scan_mgr_jtag_io(JTAG_BP_INSN | JTAG_BP_TMS, 0x02 | (1 << 4), 0x0);
+
+       /*
+        * Push 4 bytes of data through TDI->DR->TDO.
+        *
+        * Length of TDI data is 32bits (length - 1) and they are only
+        * zeroes as we care only for TDO data.
+        */
+       ret = scan_mgr_jtag_insn_data(0x4, &data, 32);
+       /* Read 32 bit from captured JTAG data. */
+       if (!ret)
+               id = readl(&scan_manager_base->fifo_quad_byte);
+
+       /* Disable all port */
+       writel(0, &scan_manager_base->en);
+       writel(0, &sys_mgr_base->scanmgrgrp_ctrl);
+
+       return id;
+}