1 /* 2 * (c) Copyright 2010-2017 Xilinx, Inc. All rights reserved. 3 * (c) Copyright 2016 Topic Embedded Products. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <asm/io.h> 9 #include <asm/spl.h> 10 #include <asm/arch/sys_proto.h> 11 #include <asm/arch/ps7_init_gpl.h> 12 13 __weak int ps7_init(void) 14 { 15 /* 16 * This function is overridden by the one in 17 * board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists. 18 */ 19 return 0; 20 } 21 22 __weak int ps7_post_config(void) 23 { 24 /* 25 * This function is overridden by the one in 26 * board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists. 27 */ 28 return 0; 29 } 30 31 /* For delay calculation using global registers*/ 32 #define SCU_GLOBAL_TIMER_COUNT_L32 0xF8F00200 33 #define SCU_GLOBAL_TIMER_COUNT_U32 0xF8F00204 34 #define SCU_GLOBAL_TIMER_CONTROL 0xF8F00208 35 #define SCU_GLOBAL_TIMER_AUTO_INC 0xF8F00218 36 #define APU_FREQ 666666666 37 38 #define PS7_MASK_POLL_TIME 100000000 39 40 /* IO accessors. No memory barriers desired. */ 41 static inline void iowrite(unsigned long val, unsigned long addr) 42 { 43 __raw_writel(val, addr); 44 } 45 46 static inline unsigned long ioread(unsigned long addr) 47 { 48 return __raw_readl(addr); 49 } 50 51 /* start timer */ 52 static void perf_start_clock(void) 53 { 54 iowrite((1 << 0) | /* Timer Enable */ 55 (1 << 3) | /* Auto-increment */ 56 (0 << 8), /* Pre-scale */ 57 SCU_GLOBAL_TIMER_CONTROL); 58 } 59 60 /* Compute mask for given delay in miliseconds*/ 61 static int get_number_of_cycles_for_delay(unsigned int delay) 62 { 63 return (APU_FREQ / (2 * 1000)) * delay; 64 } 65 66 /* stop timer */ 67 static void perf_disable_clock(void) 68 { 69 iowrite(0, SCU_GLOBAL_TIMER_CONTROL); 70 } 71 72 /* stop timer and reset timer count regs */ 73 static void perf_reset_clock(void) 74 { 75 perf_disable_clock(); 76 iowrite(0, SCU_GLOBAL_TIMER_COUNT_L32); 77 iowrite(0, SCU_GLOBAL_TIMER_COUNT_U32); 78 } 79 80 static void perf_reset_and_start_timer(void) 81 { 82 perf_reset_clock(); 83 perf_start_clock(); 84 } 85 86 int __weak ps7_config(unsigned long *ps7_config_init) 87 { 88 unsigned long *ptr = ps7_config_init; 89 unsigned long opcode; 90 unsigned long addr; 91 unsigned long val; 92 unsigned long mask; 93 unsigned int numargs; 94 int i; 95 int delay; 96 97 for (;;) { 98 opcode = ptr[0]; 99 if (opcode == OPCODE_EXIT) 100 return PS7_INIT_SUCCESS; 101 addr = (opcode & OPCODE_ADDRESS_MASK); 102 103 switch (opcode & ~OPCODE_ADDRESS_MASK) { 104 case OPCODE_MASKWRITE: 105 numargs = 3; 106 mask = ptr[1]; 107 val = ptr[2]; 108 iowrite((ioread(addr) & ~mask) | (val & mask), addr); 109 break; 110 111 case OPCODE_WRITE: 112 numargs = 2; 113 val = ptr[1]; 114 iowrite(val, addr); 115 break; 116 117 case OPCODE_MASKPOLL: 118 numargs = 2; 119 mask = ptr[1]; 120 i = 0; 121 while (!(ioread(addr) & mask)) { 122 if (i == PS7_MASK_POLL_TIME) 123 return PS7_INIT_TIMEOUT; 124 i++; 125 } 126 break; 127 128 case OPCODE_MASKDELAY: 129 numargs = 2; 130 mask = ptr[1]; 131 delay = get_number_of_cycles_for_delay(mask); 132 perf_reset_and_start_timer(); 133 while (ioread(addr) < delay) 134 ; 135 break; 136 137 default: 138 return PS7_INIT_CORRUPT; 139 } 140 141 ptr += numargs; 142 } 143 } 144 145 unsigned long __weak __maybe_unused ps7GetSiliconVersion(void) 146 { 147 return zynq_get_silicon_version(); 148 } 149