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