10SN/A// SPDX-License-Identifier: GPL-2.0+ 22362SN/A/* 30SN/A * (c) Copyright 2010-2017 Xilinx, Inc. All rights reserved. 40SN/A * (c) Copyright 2016 Topic Embedded Products. 50SN/A */ 60SN/A 72362SN/A#include <asm/io.h> 80SN/A#include <asm/spl.h> 92362SN/A#include <asm/arch/sys_proto.h> 100SN/A#include <asm/arch/ps7_init_gpl.h> 110SN/A 120SN/A__weak int ps7_init(void) 130SN/A{ 140SN/A /* 150SN/A * This function is overridden by the one in 160SN/A * board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists. 170SN/A */ 180SN/A return 0; 190SN/A} 200SN/A 212362SN/A__weak int ps7_post_config(void) 222362SN/A{ 232362SN/A /* 240SN/A * This function is overridden by the one in 250SN/A * board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists. 260SN/A */ 270SN/A return 0; 280SN/A} 290SN/A 300SN/A/* For delay calculation using global registers*/ 310SN/A#define SCU_GLOBAL_TIMER_COUNT_L32 0xF8F00200 320SN/A#define SCU_GLOBAL_TIMER_COUNT_U32 0xF8F00204 330SN/A#define SCU_GLOBAL_TIMER_CONTROL 0xF8F00208 340SN/A#define SCU_GLOBAL_TIMER_AUTO_INC 0xF8F00218 350SN/A#define APU_FREQ 666666666 360SN/A 370SN/A#define PS7_MASK_POLL_TIME 100000000 380SN/A 390SN/A/* IO accessors. No memory barriers desired. */ 400SN/Astatic inline void iowrite(unsigned long val, unsigned long addr) 410SN/A{ 420SN/A __raw_writel(val, addr); 430SN/A} 440SN/A 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