Linux 4.16-rc2
[linux-2.6-block.git] / arch / metag / kernel / core_reg.c
CommitLineData
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 */
42void 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}
72EXPORT_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 */
84unsigned 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}
118EXPORT_SYMBOL(core_reg_read);