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