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