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