Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / metag / kernel / core_reg.c
1 /*
2  *  Support for reading and writing Meta core internal registers.
3  *
4  *  Copyright (C) 2011 Imagination Technologies Ltd.
5  *
6  */
7
8 #include <linux/delay.h>
9 #include <linux/export.h>
10
11 #include <asm/core_reg.h>
12 #include <asm/global_lock.h>
13 #include <asm/hwthread.h>
14 #include <asm/io.h>
15 #include <asm/metag_mem.h>
16 #include <asm/metag_regs.h>
17
18 #define UNIT_BIT_MASK           TXUXXRXRQ_UXX_BITS
19 #define REG_BIT_MASK            TXUXXRXRQ_RX_BITS
20 #define THREAD_BIT_MASK         TXUXXRXRQ_TX_BITS
21
22 #define UNIT_SHIFTS             TXUXXRXRQ_UXX_S
23 #define REG_SHIFTS              TXUXXRXRQ_RX_S
24 #define THREAD_SHIFTS           TXUXXRXRQ_TX_S
25
26 #define UNIT_VAL(x)             (((x) << UNIT_SHIFTS) & UNIT_BIT_MASK)
27 #define REG_VAL(x)              (((x) << REG_SHIFTS) & REG_BIT_MASK)
28 #define THREAD_VAL(x)           (((x) << THREAD_SHIFTS) & THREAD_BIT_MASK)
29
30 /*
31  * core_reg_write() - modify the content of a register in a core unit.
32  * @unit:       The unit to be modified.
33  * @reg:        Register number within the unit.
34  * @thread:     The thread we want to access.
35  * @val:        The new value to write.
36  *
37  * Check asm/metag_regs.h for a list/defines of supported units (ie: TXUPC_ID,
38  * TXUTR_ID, etc), and regnums within the units (ie: TXMASKI_REGNUM,
39  * TXPOLLI_REGNUM, etc).
40  */
41 void core_reg_write(int unit, int reg, int thread, unsigned int val)
42 {
43         unsigned long flags;
44
45         /* TXUCT_ID has its own memory mapped registers */
46         if (unit == TXUCT_ID) {
47                 void __iomem *cu_reg = __CU_addr(thread, reg);
48                 metag_out32(val, cu_reg);
49                 return;
50         }
51
52         __global_lock2(flags);
53
54         /* wait for ready */
55         while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
56                 udelay(10);
57
58         /* set the value to write */
59         metag_out32(val, TXUXXRXDT);
60
61         /* set the register to write */
62         val = UNIT_VAL(unit) | REG_VAL(reg) | THREAD_VAL(thread);
63         metag_out32(val, TXUXXRXRQ);
64
65         /* wait for finish */
66         while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
67                 udelay(10);
68
69         __global_unlock2(flags);
70 }
71 EXPORT_SYMBOL(core_reg_write);
72
73 /*
74  * core_reg_read() - read the content of a register in a core unit.
75  * @unit:       The unit to be modified.
76  * @reg:        Register number within the unit.
77  * @thread:     The thread we want to access.
78  *
79  * Check asm/metag_regs.h for a list/defines of supported units (ie: TXUPC_ID,
80  * TXUTR_ID, etc), and regnums within the units (ie: TXMASKI_REGNUM,
81  * TXPOLLI_REGNUM, etc).
82  */
83 unsigned int core_reg_read(int unit, int reg, int thread)
84 {
85         unsigned long flags;
86         unsigned int val;
87
88         /* TXUCT_ID has its own memory mapped registers */
89         if (unit == TXUCT_ID) {
90                 void __iomem *cu_reg = __CU_addr(thread, reg);
91                 val = metag_in32(cu_reg);
92                 return val;
93         }
94
95         __global_lock2(flags);
96
97         /* wait for ready */
98         while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
99                 udelay(10);
100
101         /* set the register to read */
102         val = (UNIT_VAL(unit) | REG_VAL(reg) | THREAD_VAL(thread) |
103                                                         TXUXXRXRQ_RDnWR_BIT);
104         metag_out32(val, TXUXXRXRQ);
105
106         /* wait for finish */
107         while (!(metag_in32(TXUXXRXRQ) & TXUXXRXRQ_DREADY_BIT))
108                 udelay(10);
109
110         /* read the register value */
111         val = metag_in32(TXUXXRXDT);
112
113         __global_unlock2(flags);
114
115         return val;
116 }
117 EXPORT_SYMBOL(core_reg_read);