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