blob: 5a4744c296a2d4aeaad63a31c1413955b7aa89ad [file] [log] [blame]
Stefan Bosch95e9a8e2020-07-10 19:07:26 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2016 Nexell
4 * Youngbok, Park <park@nexell.co.kr>
5 */
6
7#include <common.h>
8#include <asm/arch/nexell.h>
9#include <asm/arch/clk.h>
10#include <asm/arch/reset.h>
11#include <asm/arch/nx_gpio.h>
12#include <asm/arch/tieoff.h>
13#include <asm/arch/sec_reg.h>
14
15#define NX_PIN_FN_SIZE 4
16#define TIEOFF_REG_NUM 33
17
18struct nx_tieoff_registerset {
19 u32 tieoffreg[TIEOFF_REG_NUM];
20};
21
22static struct nx_tieoff_registerset *nx_tieoff = (void *)PHY_BASEADDR_TIEOFF;
23
24static int tieoff_readl(void __iomem *reg)
25{
26 if (IS_ENABLED(CONFIG_ARCH_S5P4418))
27 return read_sec_reg_by_id(reg, NEXELL_TOFF_SEC_ID);
28 else
29 return readl(reg);
30}
31
32static int tieoff_writetl(void __iomem *reg, int val)
33{
34 if (IS_ENABLED(CONFIG_ARCH_S5P4418))
35 return write_sec_reg_by_id(reg, val, NEXELL_TOFF_SEC_ID);
36 else
37 return writel(val, reg);
38}
39
40void nx_tieoff_set(u32 tieoff_index, u32 tieoff_value)
41{
42 u32 regindex, mask;
43 u32 lsb, msb;
44 u32 regval;
45
46 u32 position;
47 u32 bitwidth;
48
49 position = tieoff_index & 0xffff;
50 bitwidth = (tieoff_index >> 16) & 0xffff;
51
52 regindex = position >> 5;
53
54 lsb = position & 0x1F;
55 msb = lsb + bitwidth;
56
57 if (msb > 32) {
58 msb &= 0x1F;
59 mask = ~(0xffffffff << lsb);
60 regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
61 regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) << lsb);
62 tieoff_writetl(&nx_tieoff->tieoffreg[regindex], regval);
63
64 mask = (0xffffffff << msb);
65 regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
66 regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) >> msb);
67 tieoff_writetl(&nx_tieoff->tieoffreg[regindex + 1], regval);
68 } else {
69 mask = (0xffffffff << msb) | (~(0xffffffff << lsb));
70 regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
71 regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) << lsb);
72 tieoff_writetl(&nx_tieoff->tieoffreg[regindex], regval);
73 }
74}
75
76u32 nx_tieoff_get(u32 tieoff_index)
77{
78 u32 regindex, mask;
79 u32 lsb, msb;
80 u32 regval;
81
82 u32 position;
83 u32 bitwidth;
84
85 position = tieoff_index & 0xffff;
86 bitwidth = (tieoff_index >> 16) & 0xffff;
87
88 regindex = position / 32;
89 lsb = position % 32;
90 msb = lsb + bitwidth;
91
92 if (msb > 32) {
93 msb &= 0x1F;
94 mask = 0xffffffff << lsb;
95 regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
96 regval >>= lsb;
97
98 mask = ~(0xffffffff << msb);
99 regval |= ((tieoff_readl(&nx_tieoff->tieoffreg[regindex + 1])
100 & mask) << (32 - lsb));
101 } else {
102 mask = ~(0xffffffff << msb) & (0xffffffff << lsb);
103 regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
104 regval >>= lsb;
105 }
106 return regval;
107}