diff options
Diffstat (limited to 'kernel/arch/metag/kernel/core_reg.c')
-rw-r--r-- | kernel/arch/metag/kernel/core_reg.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/kernel/arch/metag/kernel/core_reg.c b/kernel/arch/metag/kernel/core_reg.c new file mode 100644 index 000000000..671cce8c3 --- /dev/null +++ b/kernel/arch/metag/kernel/core_reg.c @@ -0,0 +1,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); |