diff options
Diffstat (limited to 'arch/arm/cpu/armv7/zynq')
| -rw-r--r-- | arch/arm/cpu/armv7/zynq/slcr.c | 61 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/zynq/timer.c | 45 | 
2 files changed, 98 insertions, 8 deletions
| diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c index 788a8fd14..52048c676 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/cpu/armv7/zynq/slcr.c @@ -28,6 +28,9 @@  #define SLCR_LOCK_MAGIC		0x767B  #define SLCR_UNLOCK_MAGIC	0xDF0D +#define SLCR_IDCODE_MASK	0x1F000 +#define SLCR_IDCODE_SHIFT	12 +  static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */  void zynq_slcr_lock(void) @@ -61,3 +64,61 @@ void zynq_slcr_cpu_reset(void)  	writel(1, &slcr_base->pss_rst_ctrl);  } + +/* Setup clk for network */ +void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk) +{ +	zynq_slcr_unlock(); + +	if (gem_id > 1) { +		printf("Non existing GEM id %d\n", gem_id); +		goto out; +	} + +	if (gem_id) { +		/* Set divisors for appropriate frequency in GEM_CLK_CTRL */ +		writel(clk, &slcr_base->gem1_clk_ctrl); +		/* Configure GEM_RCLK_CTRL */ +		writel(rclk, &slcr_base->gem1_rclk_ctrl); +	} else { +		/* Set divisors for appropriate frequency in GEM_CLK_CTRL */ +		writel(clk, &slcr_base->gem0_clk_ctrl); +		/* Configure GEM_RCLK_CTRL */ +		writel(rclk, &slcr_base->gem0_rclk_ctrl); +	} + +out: +	zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_disable(void) +{ +	zynq_slcr_unlock(); + +	/* Disable AXI interface */ +	writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl); + +	/* Set Level Shifters DT618760 */ +	writel(0xA, &slcr_base->lvl_shftr_en); + +	zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_enable(void) +{ +	zynq_slcr_unlock(); + +	/* Set Level Shifters DT618760 */ +	writel(0xF, &slcr_base->lvl_shftr_en); + +	/* Disable AXI interface */ +	writel(0x0, &slcr_base->fpga_rst_ctrl); + +	zynq_slcr_lock(); +} + +u32 zynq_slcr_get_idcode(void) +{ +	return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >> +							SLCR_IDCODE_SHIFT; +} diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c index 45b405a4b..8c4357de4 100644 --- a/arch/arm/cpu/armv7/zynq/timer.c +++ b/arch/arm/cpu/armv7/zynq/timer.c @@ -44,6 +44,7 @@  #include <common.h>  #include <div64.h>  #include <asm/io.h> +#include <asm/arch/hardware.h>  DECLARE_GLOBAL_DATA_PTR; @@ -54,7 +55,7 @@ struct scu_timer {  };  static struct scu_timer *timer_base = -			      (struct scu_timer *) CONFIG_SCUTIMER_BASEADDR; +			      (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR;  #define SCUTIMER_CONTROL_PRESCALER_MASK	0x0000FF00 /* Prescaler */  #define SCUTIMER_CONTROL_PRESCALER_SHIFT	8 @@ -114,15 +115,43 @@ ulong get_timer_masked(void)  void __udelay(unsigned long usec)  { -	unsigned long long tmp; -	ulong tmo; +	u32 countticks; +	u32 timeend; +	u32 timediff; +	u32 timenow; -	tmo = usec / (1000000 / CONFIG_SYS_HZ); -	tmp = get_ticks() + tmo; /* Get current timestamp */ +	if (usec == 0) +		return; -	while (get_ticks() < tmp) { /* Loop till event */ -		 /* NOP */; -	} +	countticks = (u32) (((unsigned long long) TIMER_TICK_HZ * usec) / +								1000000); + +	/* decrementing timer */ +	timeend = readl(&timer_base->counter) - countticks; + +#if TIMER_LOAD_VAL != 0xFFFFFFFF +	/* do not manage multiple overflow */ +	if (countticks >= TIMER_LOAD_VAL) +		countticks = TIMER_LOAD_VAL - 1; +#endif + +	do { +		timenow = readl(&timer_base->counter); + +		if (timenow >= timeend) { +			/* normal case */ +			timediff = timenow - timeend; +		} else { +			if ((TIMER_LOAD_VAL - timeend + timenow) <= +								countticks) { +				/* overflow */ +				timediff = TIMER_LOAD_VAL - timeend + timenow; +			} else { +				/* missed the exact match */ +				break; +			} +		} +	} while (timediff > 0);  }  /* Timer without interrupts */ |