huangcm
2025-08-30 0269911b91ed7e03c24005924cc6423abf245fb8
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
/*
 *  Support for reading and writing Meta core internal registers.
 *
 *  Copyright (C) 2011 Imagination Technologies Ltd.
 *
 */
 
#include <linux/delay.h>
#include <linux/export.h>
 
#include <asm/core_reg.h>
#include <asm/global_lock.h>
#include <asm/hwthread.h>
#include <asm/io.h>
#include <asm/metag_mem.h>
#include <asm/metag_regs.h>
 
#define UNIT_BIT_MASK        TXUXXRXRQ_UXX_BITS
#define REG_BIT_MASK        TXUXXRXRQ_RX_BITS
#define THREAD_BIT_MASK        TXUXXRXRQ_TX_BITS
 
#define UNIT_SHIFTS        TXUXXRXRQ_UXX_S
#define REG_SHIFTS        TXUXXRXRQ_RX_S
#define THREAD_SHIFTS        TXUXXRXRQ_TX_S
 
#define UNIT_VAL(x)        (((x) << UNIT_SHIFTS) & UNIT_BIT_MASK)
#define REG_VAL(x)        (((x) << REG_SHIFTS) & REG_BIT_MASK)
#define THREAD_VAL(x)        (((x) << THREAD_SHIFTS) & THREAD_BIT_MASK)
 
/*
 * core_reg_write() - modify the content of a register in a core unit.
 * @unit:    The unit to be modified.
 * @reg:    Register number within the unit.
 * @thread:    The thread we want to access.
 * @val:    The new value to write.
 *
 * Check asm/metag_regs.h for a list/defines of supported units (ie: TXUPC_ID,
 * TXUTR_ID, etc), and regnums within the units (ie: TXMASKI_REGNUM,
 * TXPOLLI_REGNUM, etc).
 */
void core_reg_write(int unit, int reg, int thread, unsigned int val)
{
   unsigned long flags;
 
   /* TXUCT_ID has its own memory mapped registers */
   if (unit == TXUCT_ID) {
       void __iomem *cu_reg = __CU_addr(thread, reg);
       metag_out32(val, cu_reg);
       return;
   }
 
   __global_lock2(flags);
 
   /* wait for ready */
   while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
       udelay(10);
 
   /* set the value to write */
   metag_out32(val, TXUXXRXDT);
 
   /* set the register to write */
   val = UNIT_VAL(unit) | REG_VAL(reg) | THREAD_VAL(thread);
   metag_out32(val, TXUXXRXRQ);
 
   /* wait for finish */
   while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
       udelay(10);
 
   __global_unlock2(flags);
}
EXPORT_SYMBOL(core_reg_write);
 
/*
 * core_reg_read() - read the content of a register in a core unit.
 * @unit:    The unit to be modified.
 * @reg:    Register number within the unit.
 * @thread:    The thread we want to access.
 *
 * Check asm/metag_regs.h for a list/defines of supported units (ie: TXUPC_ID,
 * TXUTR_ID, etc), and regnums within the units (ie: TXMASKI_REGNUM,
 * TXPOLLI_REGNUM, etc).
 */
unsigned int core_reg_read(int unit, int reg, int thread)
{
   unsigned long flags;
   unsigned int val;
 
   /* TXUCT_ID has its own memory mapped registers */
   if (unit == TXUCT_ID) {
       void __iomem *cu_reg = __CU_addr(thread, reg);
       val = metag_in32(cu_reg);
       return val;
   }
 
   __global_lock2(flags);
 
   /* wait for ready */
   while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
       udelay(10);
 
   /* set the register to read */
   val = (UNIT_VAL(unit) | REG_VAL(reg) | THREAD_VAL(thread) |
                           TXUXXRXRQ_RDnWR_BIT);
   metag_out32(val, TXUXXRXRQ);
 
   /* wait for finish */
   while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
       udelay(10);
 
   /* read the register value */
   val = metag_in32(TXUXXRXDT);
 
   __global_unlock2(flags);
 
   return val;
}
EXPORT_SYMBOL(core_reg_read);