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