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