105a21721SMasahiro Yamada /*
205a21721SMasahiro Yamada  * Copyright (C) 2012 Altera Corporation <www.altera.com>
305a21721SMasahiro Yamada  * All rights reserved.
405a21721SMasahiro Yamada  *
505a21721SMasahiro Yamada  * This file contains only support functions used also by the SoCFPGA
605a21721SMasahiro Yamada  * platform code, the real meat is located in drivers/fpga/socfpga.c .
705a21721SMasahiro Yamada  *
805a21721SMasahiro Yamada  * SPDX-License-Identifier:	BSD-3-Clause
905a21721SMasahiro Yamada  */
1005a21721SMasahiro Yamada 
1105a21721SMasahiro Yamada #include <common.h>
1205a21721SMasahiro Yamada #include <asm/io.h>
13*1221ce45SMasahiro Yamada #include <linux/errno.h>
1405a21721SMasahiro Yamada #include <asm/arch/fpga_manager.h>
1505a21721SMasahiro Yamada #include <asm/arch/reset_manager.h>
1605a21721SMasahiro Yamada #include <asm/arch/system_manager.h>
1705a21721SMasahiro Yamada 
1805a21721SMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
1905a21721SMasahiro Yamada 
2005a21721SMasahiro Yamada /* Timeout count */
2105a21721SMasahiro Yamada #define FPGA_TIMEOUT_CNT		0x1000000
2205a21721SMasahiro Yamada 
2305a21721SMasahiro Yamada static struct socfpga_fpga_manager *fpgamgr_regs =
2405a21721SMasahiro Yamada 	(struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS;
2505a21721SMasahiro Yamada 
2605a21721SMasahiro Yamada /* Check whether FPGA Init_Done signal is high */
2705a21721SMasahiro Yamada static int is_fpgamgr_initdone_high(void)
2805a21721SMasahiro Yamada {
2905a21721SMasahiro Yamada 	unsigned long val;
3005a21721SMasahiro Yamada 
3105a21721SMasahiro Yamada 	val = readl(&fpgamgr_regs->gpio_ext_porta);
3205a21721SMasahiro Yamada 	return val & FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK;
3305a21721SMasahiro Yamada }
3405a21721SMasahiro Yamada 
3505a21721SMasahiro Yamada /* Get the FPGA mode */
3605a21721SMasahiro Yamada int fpgamgr_get_mode(void)
3705a21721SMasahiro Yamada {
3805a21721SMasahiro Yamada 	unsigned long val;
3905a21721SMasahiro Yamada 
4005a21721SMasahiro Yamada 	val = readl(&fpgamgr_regs->stat);
4105a21721SMasahiro Yamada 	return val & FPGAMGRREGS_STAT_MODE_MASK;
4205a21721SMasahiro Yamada }
4305a21721SMasahiro Yamada 
4405a21721SMasahiro Yamada /* Check whether FPGA is ready to be accessed */
4505a21721SMasahiro Yamada int fpgamgr_test_fpga_ready(void)
4605a21721SMasahiro Yamada {
4705a21721SMasahiro Yamada 	/* Check for init done signal */
4805a21721SMasahiro Yamada 	if (!is_fpgamgr_initdone_high())
4905a21721SMasahiro Yamada 		return 0;
5005a21721SMasahiro Yamada 
5105a21721SMasahiro Yamada 	/* Check again to avoid false glitches */
5205a21721SMasahiro Yamada 	if (!is_fpgamgr_initdone_high())
5305a21721SMasahiro Yamada 		return 0;
5405a21721SMasahiro Yamada 
5505a21721SMasahiro Yamada 	if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_USERMODE)
5605a21721SMasahiro Yamada 		return 0;
5705a21721SMasahiro Yamada 
5805a21721SMasahiro Yamada 	return 1;
5905a21721SMasahiro Yamada }
6005a21721SMasahiro Yamada 
6105a21721SMasahiro Yamada /* Poll until FPGA is ready to be accessed or timeout occurred */
6205a21721SMasahiro Yamada int fpgamgr_poll_fpga_ready(void)
6305a21721SMasahiro Yamada {
6405a21721SMasahiro Yamada 	unsigned long i;
6505a21721SMasahiro Yamada 
6605a21721SMasahiro Yamada 	/* If FPGA is blank, wait till WD invoke warm reset */
6705a21721SMasahiro Yamada 	for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
6805a21721SMasahiro Yamada 		/* check for init done signal */
6905a21721SMasahiro Yamada 		if (!is_fpgamgr_initdone_high())
7005a21721SMasahiro Yamada 			continue;
7105a21721SMasahiro Yamada 		/* check again to avoid false glitches */
7205a21721SMasahiro Yamada 		if (!is_fpgamgr_initdone_high())
7305a21721SMasahiro Yamada 			continue;
7405a21721SMasahiro Yamada 		return 1;
7505a21721SMasahiro Yamada 	}
7605a21721SMasahiro Yamada 
7705a21721SMasahiro Yamada 	return 0;
7805a21721SMasahiro Yamada }
79