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. */ 40static inline void iowrite(unsigned long val, unsigned long addr) 41{ 42 __raw_writel(val, addr); 43} 44 45static inline unsigned long ioread(unsigned long addr) 46{ 47 return __raw_readl(addr); 48} 49 50/* start timer */ 51static 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*/ 60static unsigned long get_number_of_cycles_for_delay(unsigned long delay) 61{ 62 return (APU_FREQ / (2 * 1000)) * delay; 63} 64 65/* stop timer */ 66static void perf_disable_clock(void) 67{ 68 iowrite(0, SCU_GLOBAL_TIMER_CONTROL); 69} 70 71/* stop timer and reset timer count regs */ 72static 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 79static void perf_reset_and_start_timer(void) 80{ 81 perf_reset_clock(); 82 perf_start_clock(); 83} 84 85int __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 144unsigned long __weak __maybe_unused ps7GetSiliconVersion(void) 145{ 146 return zynq_get_silicon_version(); 147} 148