1 // 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
18 struct nx_tieoff_registerset {
19 u32 tieoffreg[TIEOFF_REG_NUM];
20 };
21
22 static struct nx_tieoff_registerset *nx_tieoff = (void *)PHY_BASEADDR_TIEOFF;
23
tieoff_readl(void __iomem * reg)24 static 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
tieoff_writetl(void __iomem * reg,int val)32 static 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
nx_tieoff_set(u32 tieoff_index,u32 tieoff_value)40 void 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
nx_tieoff_get(u32 tieoff_index)76 u32 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 }
108