Commit | Line | Data |
---|---|---|
42682c6c JH |
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); |