diff options
author | Olof Johansson <olof@lixom.net> | 2015-04-03 17:49:52 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2015-04-03 17:49:52 -0400 |
commit | 9d8633915ba52158d53b016d276ca30616a6e6b3 (patch) | |
tree | 4e1d1e4f627563c594cd5c69e8424db94f4cb1f3 | |
parent | 47f36e4921ae11dccf3163f75f70bb55686780f1 (diff) | |
parent | 1f022d84bd193ec88b01c6d2cb5b6647cb20a02f (diff) |
Merge tag 'v4.0-next-soc' of https://github.com/mbgg/linux-mediatek into next/drivers
Merge "ARM: mediatek: soc updates for v4.1" from Matthias Brugger:
- enable the pin controller in Kconfig
- Add PMIC wrapper for MT8135 and MT8173 SoCs
* tag 'v4.0-next-soc' of https://github.com/mbgg/linux-mediatek:
soc: mediatek: Add PMIC wrapper for MT8135 and MT8173 SoCs
ARM: mediatek: enable the pin controller
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | arch/arm/mach-mediatek/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/mediatek/Kconfig | 11 | ||||
-rw-r--r-- | drivers/soc/mediatek/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-pmic-wrap.c | 977 |
6 files changed, 992 insertions, 0 deletions
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig index f7e463ca0287..9f59e58da3a4 100644 --- a/arch/arm/mach-mediatek/Kconfig +++ b/arch/arm/mach-mediatek/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | menuconfig ARCH_MEDIATEK | 1 | menuconfig ARCH_MEDIATEK |
2 | bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7 | 2 | bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7 |
3 | select ARM_GIC | 3 | select ARM_GIC |
4 | select PINCTRL | ||
4 | select MTK_TIMER | 5 | select MTK_TIMER |
5 | help | 6 | help |
6 | Support for Mediatek MT65xx & MT81xx SoCs | 7 | Support for Mediatek MT65xx & MT81xx SoCs |
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index 76d6bd4da138..d8bde82f0370 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | menu "SOC (System On Chip) specific Drivers" | 1 | menu "SOC (System On Chip) specific Drivers" |
2 | 2 | ||
3 | source "drivers/soc/mediatek/Kconfig" | ||
3 | source "drivers/soc/qcom/Kconfig" | 4 | source "drivers/soc/qcom/Kconfig" |
4 | source "drivers/soc/ti/Kconfig" | 5 | source "drivers/soc/ti/Kconfig" |
5 | source "drivers/soc/versatile/Kconfig" | 6 | source "drivers/soc/versatile/Kconfig" |
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 063113d0bd38..70042b259744 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | # Makefile for the Linux Kernel SOC specific device drivers. | 2 | # Makefile for the Linux Kernel SOC specific device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ | ||
5 | obj-$(CONFIG_ARCH_QCOM) += qcom/ | 6 | obj-$(CONFIG_ARCH_QCOM) += qcom/ |
6 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ | 7 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ |
7 | obj-$(CONFIG_SOC_TI) += ti/ | 8 | obj-$(CONFIG_SOC_TI) += ti/ |
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig new file mode 100644 index 000000000000..bcdb22d5e215 --- /dev/null +++ b/drivers/soc/mediatek/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # MediaTek SoC drivers | ||
3 | # | ||
4 | config MTK_PMIC_WRAP | ||
5 | tristate "MediaTek PMIC Wrapper Support" | ||
6 | depends on ARCH_MEDIATEK | ||
7 | select REGMAP | ||
8 | help | ||
9 | Say yes here to add support for MediaTek PMIC Wrapper found | ||
10 | on different MediaTek SoCs. The PMIC wrapper is a proprietary | ||
11 | hardware to connect the PMIC. | ||
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile new file mode 100644 index 000000000000..ecaf4defd7f6 --- /dev/null +++ b/drivers/soc/mediatek/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o | |||
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c new file mode 100644 index 000000000000..4a38506154c6 --- /dev/null +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c | |||
@@ -0,0 +1,977 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MediaTek Inc. | ||
3 | * Author: Flora Fu, MediaTek | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of_device.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/reset.h> | ||
23 | |||
24 | #define PWRAP_MT8135_BRIDGE_IORD_ARB_EN 0x4 | ||
25 | #define PWRAP_MT8135_BRIDGE_WACS3_EN 0x10 | ||
26 | #define PWRAP_MT8135_BRIDGE_INIT_DONE3 0x14 | ||
27 | #define PWRAP_MT8135_BRIDGE_WACS4_EN 0x24 | ||
28 | #define PWRAP_MT8135_BRIDGE_INIT_DONE4 0x28 | ||
29 | #define PWRAP_MT8135_BRIDGE_INT_EN 0x38 | ||
30 | #define PWRAP_MT8135_BRIDGE_TIMER_EN 0x48 | ||
31 | #define PWRAP_MT8135_BRIDGE_WDT_UNIT 0x50 | ||
32 | #define PWRAP_MT8135_BRIDGE_WDT_SRC_EN 0x54 | ||
33 | |||
34 | /* macro for wrapper status */ | ||
35 | #define PWRAP_GET_WACS_RDATA(x) (((x) >> 0) & 0x0000ffff) | ||
36 | #define PWRAP_GET_WACS_FSM(x) (((x) >> 16) & 0x00000007) | ||
37 | #define PWRAP_GET_WACS_REQ(x) (((x) >> 19) & 0x00000001) | ||
38 | #define PWRAP_STATE_SYNC_IDLE0 (1 << 20) | ||
39 | #define PWRAP_STATE_INIT_DONE0 (1 << 21) | ||
40 | |||
41 | /* macro for WACS FSM */ | ||
42 | #define PWRAP_WACS_FSM_IDLE 0x00 | ||
43 | #define PWRAP_WACS_FSM_REQ 0x02 | ||
44 | #define PWRAP_WACS_FSM_WFDLE 0x04 | ||
45 | #define PWRAP_WACS_FSM_WFVLDCLR 0x06 | ||
46 | #define PWRAP_WACS_INIT_DONE 0x01 | ||
47 | #define PWRAP_WACS_WACS_SYNC_IDLE 0x01 | ||
48 | #define PWRAP_WACS_SYNC_BUSY 0x00 | ||
49 | |||
50 | /* macro for device wrapper default value */ | ||
51 | #define PWRAP_DEW_READ_TEST_VAL 0x5aa5 | ||
52 | #define PWRAP_DEW_WRITE_TEST_VAL 0xa55a | ||
53 | |||
54 | /* macro for manual command */ | ||
55 | #define PWRAP_MAN_CMD_SPI_WRITE (1 << 13) | ||
56 | #define PWRAP_MAN_CMD_OP_CSH (0x0 << 8) | ||
57 | #define PWRAP_MAN_CMD_OP_CSL (0x1 << 8) | ||
58 | #define PWRAP_MAN_CMD_OP_CK (0x2 << 8) | ||
59 | #define PWRAP_MAN_CMD_OP_OUTS (0x8 << 8) | ||
60 | #define PWRAP_MAN_CMD_OP_OUTD (0x9 << 8) | ||
61 | #define PWRAP_MAN_CMD_OP_OUTQ (0xa << 8) | ||
62 | |||
63 | /* macro for slave device wrapper registers */ | ||
64 | #define PWRAP_DEW_BASE 0xbc00 | ||
65 | #define PWRAP_DEW_EVENT_OUT_EN (PWRAP_DEW_BASE + 0x0) | ||
66 | #define PWRAP_DEW_DIO_EN (PWRAP_DEW_BASE + 0x2) | ||
67 | #define PWRAP_DEW_EVENT_SRC_EN (PWRAP_DEW_BASE + 0x4) | ||
68 | #define PWRAP_DEW_EVENT_SRC (PWRAP_DEW_BASE + 0x6) | ||
69 | #define PWRAP_DEW_EVENT_FLAG (PWRAP_DEW_BASE + 0x8) | ||
70 | #define PWRAP_DEW_READ_TEST (PWRAP_DEW_BASE + 0xa) | ||
71 | #define PWRAP_DEW_WRITE_TEST (PWRAP_DEW_BASE + 0xc) | ||
72 | #define PWRAP_DEW_CRC_EN (PWRAP_DEW_BASE + 0xe) | ||
73 | #define PWRAP_DEW_CRC_VAL (PWRAP_DEW_BASE + 0x10) | ||
74 | #define PWRAP_DEW_MON_GRP_SEL (PWRAP_DEW_BASE + 0x12) | ||
75 | #define PWRAP_DEW_MON_FLAG_SEL (PWRAP_DEW_BASE + 0x14) | ||
76 | #define PWRAP_DEW_EVENT_TEST (PWRAP_DEW_BASE + 0x16) | ||
77 | #define PWRAP_DEW_CIPHER_KEY_SEL (PWRAP_DEW_BASE + 0x18) | ||
78 | #define PWRAP_DEW_CIPHER_IV_SEL (PWRAP_DEW_BASE + 0x1a) | ||
79 | #define PWRAP_DEW_CIPHER_LOAD (PWRAP_DEW_BASE + 0x1c) | ||
80 | #define PWRAP_DEW_CIPHER_START (PWRAP_DEW_BASE + 0x1e) | ||
81 | #define PWRAP_DEW_CIPHER_RDY (PWRAP_DEW_BASE + 0x20) | ||
82 | #define PWRAP_DEW_CIPHER_MODE (PWRAP_DEW_BASE + 0x22) | ||
83 | #define PWRAP_DEW_CIPHER_SWRST (PWRAP_DEW_BASE + 0x24) | ||
84 | #define PWRAP_MT8173_DEW_CIPHER_IV0 (PWRAP_DEW_BASE + 0x26) | ||
85 | #define PWRAP_MT8173_DEW_CIPHER_IV1 (PWRAP_DEW_BASE + 0x28) | ||
86 | #define PWRAP_MT8173_DEW_CIPHER_IV2 (PWRAP_DEW_BASE + 0x2a) | ||
87 | #define PWRAP_MT8173_DEW_CIPHER_IV3 (PWRAP_DEW_BASE + 0x2c) | ||
88 | #define PWRAP_MT8173_DEW_CIPHER_IV4 (PWRAP_DEW_BASE + 0x2e) | ||
89 | #define PWRAP_MT8173_DEW_CIPHER_IV5 (PWRAP_DEW_BASE + 0x30) | ||
90 | |||
91 | enum pwrap_regs { | ||
92 | PWRAP_MUX_SEL, | ||
93 | PWRAP_WRAP_EN, | ||
94 | PWRAP_DIO_EN, | ||
95 | PWRAP_SIDLY, | ||
96 | PWRAP_CSHEXT_WRITE, | ||
97 | PWRAP_CSHEXT_READ, | ||
98 | PWRAP_CSLEXT_START, | ||
99 | PWRAP_CSLEXT_END, | ||
100 | PWRAP_STAUPD_PRD, | ||
101 | PWRAP_STAUPD_GRPEN, | ||
102 | PWRAP_STAUPD_MAN_TRIG, | ||
103 | PWRAP_STAUPD_STA, | ||
104 | PWRAP_WRAP_STA, | ||
105 | PWRAP_HARB_INIT, | ||
106 | PWRAP_HARB_HPRIO, | ||
107 | PWRAP_HIPRIO_ARB_EN, | ||
108 | PWRAP_HARB_STA0, | ||
109 | PWRAP_HARB_STA1, | ||
110 | PWRAP_MAN_EN, | ||
111 | PWRAP_MAN_CMD, | ||
112 | PWRAP_MAN_RDATA, | ||
113 | PWRAP_MAN_VLDCLR, | ||
114 | PWRAP_WACS0_EN, | ||
115 | PWRAP_INIT_DONE0, | ||
116 | PWRAP_WACS0_CMD, | ||
117 | PWRAP_WACS0_RDATA, | ||
118 | PWRAP_WACS0_VLDCLR, | ||
119 | PWRAP_WACS1_EN, | ||
120 | PWRAP_INIT_DONE1, | ||
121 | PWRAP_WACS1_CMD, | ||
122 | PWRAP_WACS1_RDATA, | ||
123 | PWRAP_WACS1_VLDCLR, | ||
124 | PWRAP_WACS2_EN, | ||
125 | PWRAP_INIT_DONE2, | ||
126 | PWRAP_WACS2_CMD, | ||
127 | PWRAP_WACS2_RDATA, | ||
128 | PWRAP_WACS2_VLDCLR, | ||
129 | PWRAP_INT_EN, | ||
130 | PWRAP_INT_FLG_RAW, | ||
131 | PWRAP_INT_FLG, | ||
132 | PWRAP_INT_CLR, | ||
133 | PWRAP_SIG_ADR, | ||
134 | PWRAP_SIG_MODE, | ||
135 | PWRAP_SIG_VALUE, | ||
136 | PWRAP_SIG_ERRVAL, | ||
137 | PWRAP_CRC_EN, | ||
138 | PWRAP_TIMER_EN, | ||
139 | PWRAP_TIMER_STA, | ||
140 | PWRAP_WDT_UNIT, | ||
141 | PWRAP_WDT_SRC_EN, | ||
142 | PWRAP_WDT_FLG, | ||
143 | PWRAP_DEBUG_INT_SEL, | ||
144 | PWRAP_CIPHER_KEY_SEL, | ||
145 | PWRAP_CIPHER_IV_SEL, | ||
146 | PWRAP_CIPHER_RDY, | ||
147 | PWRAP_CIPHER_MODE, | ||
148 | PWRAP_CIPHER_SWRST, | ||
149 | PWRAP_DCM_EN, | ||
150 | PWRAP_DCM_DBC_PRD, | ||
151 | |||
152 | /* MT8135 only regs */ | ||
153 | PWRAP_CSHEXT, | ||
154 | PWRAP_EVENT_IN_EN, | ||
155 | PWRAP_EVENT_DST_EN, | ||
156 | PWRAP_RRARB_INIT, | ||
157 | PWRAP_RRARB_EN, | ||
158 | PWRAP_RRARB_STA0, | ||
159 | PWRAP_RRARB_STA1, | ||
160 | PWRAP_EVENT_STA, | ||
161 | PWRAP_EVENT_STACLR, | ||
162 | PWRAP_CIPHER_LOAD, | ||
163 | PWRAP_CIPHER_START, | ||
164 | |||
165 | /* MT8173 only regs */ | ||
166 | PWRAP_RDDMY, | ||
167 | PWRAP_SI_CK_CON, | ||
168 | PWRAP_DVFS_ADR0, | ||
169 | PWRAP_DVFS_WDATA0, | ||
170 | PWRAP_DVFS_ADR1, | ||
171 | PWRAP_DVFS_WDATA1, | ||
172 | PWRAP_DVFS_ADR2, | ||
173 | PWRAP_DVFS_WDATA2, | ||
174 | PWRAP_DVFS_ADR3, | ||
175 | PWRAP_DVFS_WDATA3, | ||
176 | PWRAP_DVFS_ADR4, | ||
177 | PWRAP_DVFS_WDATA4, | ||
178 | PWRAP_DVFS_ADR5, | ||
179 | PWRAP_DVFS_WDATA5, | ||
180 | PWRAP_DVFS_ADR6, | ||
181 | PWRAP_DVFS_WDATA6, | ||
182 | PWRAP_DVFS_ADR7, | ||
183 | PWRAP_DVFS_WDATA7, | ||
184 | PWRAP_SPMINF_STA, | ||
185 | PWRAP_CIPHER_EN, | ||
186 | }; | ||
187 | |||
188 | static int mt8173_regs[] = { | ||
189 | [PWRAP_MUX_SEL] = 0x0, | ||
190 | [PWRAP_WRAP_EN] = 0x4, | ||
191 | [PWRAP_DIO_EN] = 0x8, | ||
192 | [PWRAP_SIDLY] = 0xc, | ||
193 | [PWRAP_RDDMY] = 0x10, | ||
194 | [PWRAP_SI_CK_CON] = 0x14, | ||
195 | [PWRAP_CSHEXT_WRITE] = 0x18, | ||
196 | [PWRAP_CSHEXT_READ] = 0x1c, | ||
197 | [PWRAP_CSLEXT_START] = 0x20, | ||
198 | [PWRAP_CSLEXT_END] = 0x24, | ||
199 | [PWRAP_STAUPD_PRD] = 0x28, | ||
200 | [PWRAP_STAUPD_GRPEN] = 0x2c, | ||
201 | [PWRAP_STAUPD_MAN_TRIG] = 0x40, | ||
202 | [PWRAP_STAUPD_STA] = 0x44, | ||
203 | [PWRAP_WRAP_STA] = 0x48, | ||
204 | [PWRAP_HARB_INIT] = 0x4c, | ||
205 | [PWRAP_HARB_HPRIO] = 0x50, | ||
206 | [PWRAP_HIPRIO_ARB_EN] = 0x54, | ||
207 | [PWRAP_HARB_STA0] = 0x58, | ||
208 | [PWRAP_HARB_STA1] = 0x5c, | ||
209 | [PWRAP_MAN_EN] = 0x60, | ||
210 | [PWRAP_MAN_CMD] = 0x64, | ||
211 | [PWRAP_MAN_RDATA] = 0x68, | ||
212 | [PWRAP_MAN_VLDCLR] = 0x6c, | ||
213 | [PWRAP_WACS0_EN] = 0x70, | ||
214 | [PWRAP_INIT_DONE0] = 0x74, | ||
215 | [PWRAP_WACS0_CMD] = 0x78, | ||
216 | [PWRAP_WACS0_RDATA] = 0x7c, | ||
217 | [PWRAP_WACS0_VLDCLR] = 0x80, | ||
218 | [PWRAP_WACS1_EN] = 0x84, | ||
219 | [PWRAP_INIT_DONE1] = 0x88, | ||
220 | [PWRAP_WACS1_CMD] = 0x8c, | ||
221 | [PWRAP_WACS1_RDATA] = 0x90, | ||
222 | [PWRAP_WACS1_VLDCLR] = 0x94, | ||
223 | [PWRAP_WACS2_EN] = 0x98, | ||
224 | [PWRAP_INIT_DONE2] = 0x9c, | ||
225 | [PWRAP_WACS2_CMD] = 0xa0, | ||
226 | [PWRAP_WACS2_RDATA] = 0xa4, | ||
227 | [PWRAP_WACS2_VLDCLR] = 0xa8, | ||
228 | [PWRAP_INT_EN] = 0xac, | ||
229 | [PWRAP_INT_FLG_RAW] = 0xb0, | ||
230 | [PWRAP_INT_FLG] = 0xb4, | ||
231 | [PWRAP_INT_CLR] = 0xb8, | ||
232 | [PWRAP_SIG_ADR] = 0xbc, | ||
233 | [PWRAP_SIG_MODE] = 0xc0, | ||
234 | [PWRAP_SIG_VALUE] = 0xc4, | ||
235 | [PWRAP_SIG_ERRVAL] = 0xc8, | ||
236 | [PWRAP_CRC_EN] = 0xcc, | ||
237 | [PWRAP_TIMER_EN] = 0xd0, | ||
238 | [PWRAP_TIMER_STA] = 0xd4, | ||
239 | [PWRAP_WDT_UNIT] = 0xd8, | ||
240 | [PWRAP_WDT_SRC_EN] = 0xdc, | ||
241 | [PWRAP_WDT_FLG] = 0xe0, | ||
242 | [PWRAP_DEBUG_INT_SEL] = 0xe4, | ||
243 | [PWRAP_DVFS_ADR0] = 0xe8, | ||
244 | [PWRAP_DVFS_WDATA0] = 0xec, | ||
245 | [PWRAP_DVFS_ADR1] = 0xf0, | ||
246 | [PWRAP_DVFS_WDATA1] = 0xf4, | ||
247 | [PWRAP_DVFS_ADR2] = 0xf8, | ||
248 | [PWRAP_DVFS_WDATA2] = 0xfc, | ||
249 | [PWRAP_DVFS_ADR3] = 0x100, | ||
250 | [PWRAP_DVFS_WDATA3] = 0x104, | ||
251 | [PWRAP_DVFS_ADR4] = 0x108, | ||
252 | [PWRAP_DVFS_WDATA4] = 0x10c, | ||
253 | [PWRAP_DVFS_ADR5] = 0x110, | ||
254 | [PWRAP_DVFS_WDATA5] = 0x114, | ||
255 | [PWRAP_DVFS_ADR6] = 0x118, | ||
256 | [PWRAP_DVFS_WDATA6] = 0x11c, | ||
257 | [PWRAP_DVFS_ADR7] = 0x120, | ||
258 | [PWRAP_DVFS_WDATA7] = 0x124, | ||
259 | [PWRAP_SPMINF_STA] = 0x128, | ||
260 | [PWRAP_CIPHER_KEY_SEL] = 0x12c, | ||
261 | [PWRAP_CIPHER_IV_SEL] = 0x130, | ||
262 | [PWRAP_CIPHER_EN] = 0x134, | ||
263 | [PWRAP_CIPHER_RDY] = 0x138, | ||
264 | [PWRAP_CIPHER_MODE] = 0x13c, | ||
265 | [PWRAP_CIPHER_SWRST] = 0x140, | ||
266 | [PWRAP_DCM_EN] = 0x144, | ||
267 | [PWRAP_DCM_DBC_PRD] = 0x148, | ||
268 | }; | ||
269 | |||
270 | static int mt8135_regs[] = { | ||
271 | [PWRAP_MUX_SEL] = 0x0, | ||
272 | [PWRAP_WRAP_EN] = 0x4, | ||
273 | [PWRAP_DIO_EN] = 0x8, | ||
274 | [PWRAP_SIDLY] = 0xc, | ||
275 | [PWRAP_CSHEXT] = 0x10, | ||
276 | [PWRAP_CSHEXT_WRITE] = 0x14, | ||
277 | [PWRAP_CSHEXT_READ] = 0x18, | ||
278 | [PWRAP_CSLEXT_START] = 0x1c, | ||
279 | [PWRAP_CSLEXT_END] = 0x20, | ||
280 | [PWRAP_STAUPD_PRD] = 0x24, | ||
281 | [PWRAP_STAUPD_GRPEN] = 0x28, | ||
282 | [PWRAP_STAUPD_MAN_TRIG] = 0x2c, | ||
283 | [PWRAP_STAUPD_STA] = 0x30, | ||
284 | [PWRAP_EVENT_IN_EN] = 0x34, | ||
285 | [PWRAP_EVENT_DST_EN] = 0x38, | ||
286 | [PWRAP_WRAP_STA] = 0x3c, | ||
287 | [PWRAP_RRARB_INIT] = 0x40, | ||
288 | [PWRAP_RRARB_EN] = 0x44, | ||
289 | [PWRAP_RRARB_STA0] = 0x48, | ||
290 | [PWRAP_RRARB_STA1] = 0x4c, | ||
291 | [PWRAP_HARB_INIT] = 0x50, | ||
292 | [PWRAP_HARB_HPRIO] = 0x54, | ||
293 | [PWRAP_HIPRIO_ARB_EN] = 0x58, | ||
294 | [PWRAP_HARB_STA0] = 0x5c, | ||
295 | [PWRAP_HARB_STA1] = 0x60, | ||
296 | [PWRAP_MAN_EN] = 0x64, | ||
297 | [PWRAP_MAN_CMD] = 0x68, | ||
298 | [PWRAP_MAN_RDATA] = 0x6c, | ||
299 | [PWRAP_MAN_VLDCLR] = 0x70, | ||
300 | [PWRAP_WACS0_EN] = 0x74, | ||
301 | [PWRAP_INIT_DONE0] = 0x78, | ||
302 | [PWRAP_WACS0_CMD] = 0x7c, | ||
303 | [PWRAP_WACS0_RDATA] = 0x80, | ||
304 | [PWRAP_WACS0_VLDCLR] = 0x84, | ||
305 | [PWRAP_WACS1_EN] = 0x88, | ||
306 | [PWRAP_INIT_DONE1] = 0x8c, | ||
307 | [PWRAP_WACS1_CMD] = 0x90, | ||
308 | [PWRAP_WACS1_RDATA] = 0x94, | ||
309 | [PWRAP_WACS1_VLDCLR] = 0x98, | ||
310 | [PWRAP_WACS2_EN] = 0x9c, | ||
311 | [PWRAP_INIT_DONE2] = 0xa0, | ||
312 | [PWRAP_WACS2_CMD] = 0xa4, | ||
313 | [PWRAP_WACS2_RDATA] = 0xa8, | ||
314 | [PWRAP_WACS2_VLDCLR] = 0xac, | ||
315 | [PWRAP_INT_EN] = 0xb0, | ||
316 | [PWRAP_INT_FLG_RAW] = 0xb4, | ||
317 | [PWRAP_INT_FLG] = 0xb8, | ||
318 | [PWRAP_INT_CLR] = 0xbc, | ||
319 | [PWRAP_SIG_ADR] = 0xc0, | ||
320 | [PWRAP_SIG_MODE] = 0xc4, | ||
321 | [PWRAP_SIG_VALUE] = 0xc8, | ||
322 | [PWRAP_SIG_ERRVAL] = 0xcc, | ||
323 | [PWRAP_CRC_EN] = 0xd0, | ||
324 | [PWRAP_EVENT_STA] = 0xd4, | ||
325 | [PWRAP_EVENT_STACLR] = 0xd8, | ||
326 | [PWRAP_TIMER_EN] = 0xdc, | ||
327 | [PWRAP_TIMER_STA] = 0xe0, | ||
328 | [PWRAP_WDT_UNIT] = 0xe4, | ||
329 | [PWRAP_WDT_SRC_EN] = 0xe8, | ||
330 | [PWRAP_WDT_FLG] = 0xec, | ||
331 | [PWRAP_DEBUG_INT_SEL] = 0xf0, | ||
332 | [PWRAP_CIPHER_KEY_SEL] = 0x134, | ||
333 | [PWRAP_CIPHER_IV_SEL] = 0x138, | ||
334 | [PWRAP_CIPHER_LOAD] = 0x13c, | ||
335 | [PWRAP_CIPHER_START] = 0x140, | ||
336 | [PWRAP_CIPHER_RDY] = 0x144, | ||
337 | [PWRAP_CIPHER_MODE] = 0x148, | ||
338 | [PWRAP_CIPHER_SWRST] = 0x14c, | ||
339 | [PWRAP_DCM_EN] = 0x15c, | ||
340 | [PWRAP_DCM_DBC_PRD] = 0x160, | ||
341 | }; | ||
342 | |||
343 | enum pwrap_type { | ||
344 | PWRAP_MT8135, | ||
345 | PWRAP_MT8173, | ||
346 | }; | ||
347 | |||
348 | struct pmic_wrapper_type { | ||
349 | int *regs; | ||
350 | enum pwrap_type type; | ||
351 | u32 arb_en_all; | ||
352 | }; | ||
353 | |||
354 | static struct pmic_wrapper_type pwrap_mt8135 = { | ||
355 | .regs = mt8135_regs, | ||
356 | .type = PWRAP_MT8135, | ||
357 | .arb_en_all = 0x1ff, | ||
358 | }; | ||
359 | |||
360 | static struct pmic_wrapper_type pwrap_mt8173 = { | ||
361 | .regs = mt8173_regs, | ||
362 | .type = PWRAP_MT8173, | ||
363 | .arb_en_all = 0x3f, | ||
364 | }; | ||
365 | |||
366 | struct pmic_wrapper { | ||
367 | struct device *dev; | ||
368 | void __iomem *base; | ||
369 | struct regmap *regmap; | ||
370 | int *regs; | ||
371 | enum pwrap_type type; | ||
372 | u32 arb_en_all; | ||
373 | struct clk *clk_spi; | ||
374 | struct clk *clk_wrap; | ||
375 | struct reset_control *rstc; | ||
376 | |||
377 | struct reset_control *rstc_bridge; | ||
378 | void __iomem *bridge_base; | ||
379 | }; | ||
380 | |||
381 | static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp) | ||
382 | { | ||
383 | return wrp->type == PWRAP_MT8135; | ||
384 | } | ||
385 | |||
386 | static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp) | ||
387 | { | ||
388 | return wrp->type == PWRAP_MT8173; | ||
389 | } | ||
390 | |||
391 | static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg) | ||
392 | { | ||
393 | return readl(wrp->base + wrp->regs[reg]); | ||
394 | } | ||
395 | |||
396 | static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg) | ||
397 | { | ||
398 | writel(val, wrp->base + wrp->regs[reg]); | ||
399 | } | ||
400 | |||
401 | static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp) | ||
402 | { | ||
403 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | ||
404 | |||
405 | return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE; | ||
406 | } | ||
407 | |||
408 | static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp) | ||
409 | { | ||
410 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | ||
411 | |||
412 | return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR; | ||
413 | } | ||
414 | |||
415 | static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp) | ||
416 | { | ||
417 | return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0; | ||
418 | } | ||
419 | |||
420 | static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp) | ||
421 | { | ||
422 | u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | ||
423 | |||
424 | return (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE) && | ||
425 | (val & PWRAP_STATE_SYNC_IDLE0); | ||
426 | } | ||
427 | |||
428 | static int pwrap_wait_for_state(struct pmic_wrapper *wrp, | ||
429 | bool (*fp)(struct pmic_wrapper *)) | ||
430 | { | ||
431 | unsigned long timeout; | ||
432 | |||
433 | timeout = jiffies + usecs_to_jiffies(255); | ||
434 | |||
435 | do { | ||
436 | if (time_after(jiffies, timeout)) | ||
437 | return fp(wrp) ? 0 : -ETIMEDOUT; | ||
438 | if (fp(wrp)) | ||
439 | return 0; | ||
440 | } while (1); | ||
441 | } | ||
442 | |||
443 | static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) | ||
444 | { | ||
445 | int ret; | ||
446 | u32 val; | ||
447 | |||
448 | val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | ||
449 | if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR) | ||
450 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); | ||
451 | |||
452 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | ||
453 | if (ret) | ||
454 | return ret; | ||
455 | |||
456 | pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, | ||
457 | PWRAP_WACS2_CMD); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) | ||
463 | { | ||
464 | int ret; | ||
465 | u32 val; | ||
466 | |||
467 | val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); | ||
468 | if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR) | ||
469 | pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); | ||
470 | |||
471 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); | ||
472 | if (ret) | ||
473 | return ret; | ||
474 | |||
475 | pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD); | ||
476 | |||
477 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr); | ||
478 | if (ret) | ||
479 | return ret; | ||
480 | |||
481 | *rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA)); | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata) | ||
487 | { | ||
488 | return pwrap_read(context, adr, rdata); | ||
489 | } | ||
490 | |||
491 | static int pwrap_regmap_write(void *context, u32 adr, u32 wdata) | ||
492 | { | ||
493 | return pwrap_write(context, adr, wdata); | ||
494 | } | ||
495 | |||
496 | static int pwrap_reset_spislave(struct pmic_wrapper *wrp) | ||
497 | { | ||
498 | int ret, i; | ||
499 | |||
500 | pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN); | ||
501 | pwrap_writel(wrp, 0, PWRAP_WRAP_EN); | ||
502 | pwrap_writel(wrp, 1, PWRAP_MUX_SEL); | ||
503 | pwrap_writel(wrp, 1, PWRAP_MAN_EN); | ||
504 | pwrap_writel(wrp, 0, PWRAP_DIO_EN); | ||
505 | |||
506 | pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSL, | ||
507 | PWRAP_MAN_CMD); | ||
508 | pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS, | ||
509 | PWRAP_MAN_CMD); | ||
510 | pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSH, | ||
511 | PWRAP_MAN_CMD); | ||
512 | |||
513 | for (i = 0; i < 4; i++) | ||
514 | pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS, | ||
515 | PWRAP_MAN_CMD); | ||
516 | |||
517 | ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle); | ||
518 | if (ret) { | ||
519 | dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); | ||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | pwrap_writel(wrp, 0, PWRAP_MAN_EN); | ||
524 | pwrap_writel(wrp, 0, PWRAP_MUX_SEL); | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /* | ||
530 | * pwrap_init_sidly - configure serial input delay | ||
531 | * | ||
532 | * This configures the serial input delay. We can configure 0, 2, 4 or 6ns | ||
533 | * delay. Do a read test with all possible values and chose the best delay. | ||
534 | */ | ||
535 | static int pwrap_init_sidly(struct pmic_wrapper *wrp) | ||
536 | { | ||
537 | u32 rdata; | ||
538 | u32 i; | ||
539 | u32 pass = 0; | ||
540 | signed char dly[16] = { | ||
541 | -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1 | ||
542 | }; | ||
543 | |||
544 | for (i = 0; i < 4; i++) { | ||
545 | pwrap_writel(wrp, i, PWRAP_SIDLY); | ||
546 | pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata); | ||
547 | if (rdata == PWRAP_DEW_READ_TEST_VAL) { | ||
548 | dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i); | ||
549 | pass |= 1 << i; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | if (dly[pass] < 0) { | ||
554 | dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n", | ||
555 | pass); | ||
556 | return -EIO; | ||
557 | } | ||
558 | |||
559 | pwrap_writel(wrp, dly[pass], PWRAP_SIDLY); | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | static int pwrap_init_reg_clock(struct pmic_wrapper *wrp) | ||
565 | { | ||
566 | u32 wdata; | ||
567 | u32 rdata; | ||
568 | unsigned long rate_spi; | ||
569 | int ck_mhz; | ||
570 | |||
571 | rate_spi = clk_get_rate(wrp->clk_spi); | ||
572 | |||
573 | if (rate_spi > 26000000) | ||
574 | ck_mhz = 26; | ||
575 | else if (rate_spi > 18000000) | ||
576 | ck_mhz = 18; | ||
577 | else | ||
578 | ck_mhz = 0; | ||
579 | |||
580 | switch (ck_mhz) { | ||
581 | case 18: | ||
582 | if (pwrap_is_mt8135(wrp)) | ||
583 | pwrap_writel(wrp, 0xc, PWRAP_CSHEXT); | ||
584 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE); | ||
585 | pwrap_writel(wrp, 0xc, PWRAP_CSHEXT_READ); | ||
586 | pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START); | ||
587 | pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END); | ||
588 | break; | ||
589 | case 26: | ||
590 | if (pwrap_is_mt8135(wrp)) | ||
591 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); | ||
592 | pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); | ||
593 | pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); | ||
594 | pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START); | ||
595 | pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END); | ||
596 | break; | ||
597 | case 0: | ||
598 | if (pwrap_is_mt8135(wrp)) | ||
599 | pwrap_writel(wrp, 0xf, PWRAP_CSHEXT); | ||
600 | pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_WRITE); | ||
601 | pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_READ); | ||
602 | pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_START); | ||
603 | pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_END); | ||
604 | break; | ||
605 | default: | ||
606 | return -EINVAL; | ||
607 | } | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp) | ||
613 | { | ||
614 | return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1; | ||
615 | } | ||
616 | |||
617 | static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) | ||
618 | { | ||
619 | u32 rdata; | ||
620 | int ret; | ||
621 | |||
622 | ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata); | ||
623 | if (ret) | ||
624 | return 0; | ||
625 | |||
626 | return rdata == 1; | ||
627 | } | ||
628 | |||
629 | static int pwrap_init_cipher(struct pmic_wrapper *wrp) | ||
630 | { | ||
631 | int ret; | ||
632 | u32 rdata; | ||
633 | |||
634 | pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST); | ||
635 | pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST); | ||
636 | pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL); | ||
637 | pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL); | ||
638 | |||
639 | if (pwrap_is_mt8135(wrp)) { | ||
640 | pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD); | ||
641 | pwrap_writel(wrp, 1, PWRAP_CIPHER_START); | ||
642 | } else { | ||
643 | pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); | ||
644 | } | ||
645 | |||
646 | /* Config cipher mode @PMIC */ | ||
647 | pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1); | ||
648 | pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0); | ||
649 | pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1); | ||
650 | pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2); | ||
651 | pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1); | ||
652 | pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1); | ||
653 | |||
654 | /* wait for cipher data ready@AP */ | ||
655 | ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready); | ||
656 | if (ret) { | ||
657 | dev_err(wrp->dev, "cipher data ready@AP fail, ret=%d\n", ret); | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | /* wait for cipher data ready@PMIC */ | ||
662 | ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready); | ||
663 | if (ret) { | ||
664 | dev_err(wrp->dev, "timeout waiting for cipher data ready@PMIC\n"); | ||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | /* wait for cipher mode idle */ | ||
669 | pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1); | ||
670 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); | ||
671 | if (ret) { | ||
672 | dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret); | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE); | ||
677 | |||
678 | /* Write Test */ | ||
679 | if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) || | ||
680 | pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) || | ||
681 | (rdata != PWRAP_DEW_WRITE_TEST_VAL)) { | ||
682 | dev_err(wrp->dev, "rdata=0x%04X\n", rdata); | ||
683 | return -EFAULT; | ||
684 | } | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int pwrap_init(struct pmic_wrapper *wrp) | ||
690 | { | ||
691 | int ret; | ||
692 | u32 rdata; | ||
693 | |||
694 | reset_control_reset(wrp->rstc); | ||
695 | if (wrp->rstc_bridge) | ||
696 | reset_control_reset(wrp->rstc_bridge); | ||
697 | |||
698 | if (pwrap_is_mt8173(wrp)) { | ||
699 | /* Enable DCM */ | ||
700 | pwrap_writel(wrp, 3, PWRAP_DCM_EN); | ||
701 | pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); | ||
702 | } | ||
703 | |||
704 | /* Reset SPI slave */ | ||
705 | ret = pwrap_reset_spislave(wrp); | ||
706 | if (ret) | ||
707 | return ret; | ||
708 | |||
709 | pwrap_writel(wrp, 1, PWRAP_WRAP_EN); | ||
710 | |||
711 | pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN); | ||
712 | |||
713 | pwrap_writel(wrp, 1, PWRAP_WACS2_EN); | ||
714 | |||
715 | ret = pwrap_init_reg_clock(wrp); | ||
716 | if (ret) | ||
717 | return ret; | ||
718 | |||
719 | /* Setup serial input delay */ | ||
720 | ret = pwrap_init_sidly(wrp); | ||
721 | if (ret) | ||
722 | return ret; | ||
723 | |||
724 | /* Enable dual IO mode */ | ||
725 | pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1); | ||
726 | |||
727 | /* Check IDLE & INIT_DONE in advance */ | ||
728 | ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); | ||
729 | if (ret) { | ||
730 | dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | pwrap_writel(wrp, 1, PWRAP_DIO_EN); | ||
735 | |||
736 | /* Read Test */ | ||
737 | pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata); | ||
738 | if (rdata != PWRAP_DEW_READ_TEST_VAL) { | ||
739 | dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n", | ||
740 | PWRAP_DEW_READ_TEST_VAL, rdata); | ||
741 | return -EFAULT; | ||
742 | } | ||
743 | |||
744 | /* Enable encryption */ | ||
745 | ret = pwrap_init_cipher(wrp); | ||
746 | if (ret) | ||
747 | return ret; | ||
748 | |||
749 | /* Signature checking - using CRC */ | ||
750 | if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1)) | ||
751 | return -EFAULT; | ||
752 | |||
753 | pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); | ||
754 | pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); | ||
755 | pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR); | ||
756 | pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN); | ||
757 | |||
758 | if (pwrap_is_mt8135(wrp)) | ||
759 | pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); | ||
760 | |||
761 | pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN); | ||
762 | pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN); | ||
763 | pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN); | ||
764 | pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); | ||
765 | pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); | ||
766 | pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); | ||
767 | pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN); | ||
768 | pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); | ||
769 | pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN); | ||
770 | |||
771 | if (pwrap_is_mt8135(wrp)) { | ||
772 | /* enable pwrap events and pwrap bridge in AP side */ | ||
773 | pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN); | ||
774 | pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN); | ||
775 | writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN); | ||
776 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN); | ||
777 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN); | ||
778 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT); | ||
779 | writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN); | ||
780 | writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN); | ||
781 | writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); | ||
782 | |||
783 | /* enable PMIC event out and sources */ | ||
784 | if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || | ||
785 | pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { | ||
786 | dev_err(wrp->dev, "enable dewrap fail\n"); | ||
787 | return -EFAULT; | ||
788 | } | ||
789 | } else { | ||
790 | /* PMIC_DEWRAP enables */ | ||
791 | if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || | ||
792 | pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { | ||
793 | dev_err(wrp->dev, "enable dewrap fail\n"); | ||
794 | return -EFAULT; | ||
795 | } | ||
796 | } | ||
797 | |||
798 | /* Setup the init done registers */ | ||
799 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE2); | ||
800 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE0); | ||
801 | pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); | ||
802 | |||
803 | if (pwrap_is_mt8135(wrp)) { | ||
804 | writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); | ||
805 | writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); | ||
806 | } | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static irqreturn_t pwrap_interrupt(int irqno, void *dev_id) | ||
812 | { | ||
813 | u32 rdata; | ||
814 | struct pmic_wrapper *wrp = dev_id; | ||
815 | |||
816 | rdata = pwrap_readl(wrp, PWRAP_INT_FLG); | ||
817 | |||
818 | dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata); | ||
819 | |||
820 | pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR); | ||
821 | |||
822 | return IRQ_HANDLED; | ||
823 | } | ||
824 | |||
825 | static const struct regmap_config pwrap_regmap_config = { | ||
826 | .reg_bits = 16, | ||
827 | .val_bits = 16, | ||
828 | .reg_stride = 2, | ||
829 | .reg_read = pwrap_regmap_read, | ||
830 | .reg_write = pwrap_regmap_write, | ||
831 | .max_register = 0xffff, | ||
832 | }; | ||
833 | |||
834 | static struct of_device_id of_pwrap_match_tbl[] = { | ||
835 | { | ||
836 | .compatible = "mediatek,mt8135-pwrap", | ||
837 | .data = &pwrap_mt8135, | ||
838 | }, { | ||
839 | .compatible = "mediatek,mt8173-pwrap", | ||
840 | .data = &pwrap_mt8173, | ||
841 | }, { | ||
842 | /* sentinel */ | ||
843 | } | ||
844 | }; | ||
845 | MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); | ||
846 | |||
847 | static int pwrap_probe(struct platform_device *pdev) | ||
848 | { | ||
849 | int ret, irq; | ||
850 | struct pmic_wrapper *wrp; | ||
851 | struct device_node *np = pdev->dev.of_node; | ||
852 | const struct of_device_id *of_id = | ||
853 | of_match_device(of_pwrap_match_tbl, &pdev->dev); | ||
854 | const struct pmic_wrapper_type *type; | ||
855 | struct resource *res; | ||
856 | |||
857 | wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL); | ||
858 | if (!wrp) | ||
859 | return -ENOMEM; | ||
860 | |||
861 | platform_set_drvdata(pdev, wrp); | ||
862 | |||
863 | type = of_id->data; | ||
864 | wrp->regs = type->regs; | ||
865 | wrp->type = type->type; | ||
866 | wrp->arb_en_all = type->arb_en_all; | ||
867 | wrp->dev = &pdev->dev; | ||
868 | |||
869 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap"); | ||
870 | wrp->base = devm_ioremap_resource(wrp->dev, res); | ||
871 | if (IS_ERR(wrp->base)) | ||
872 | return PTR_ERR(wrp->base); | ||
873 | |||
874 | wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); | ||
875 | if (IS_ERR(wrp->rstc)) { | ||
876 | ret = PTR_ERR(wrp->rstc); | ||
877 | dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); | ||
878 | return ret; | ||
879 | } | ||
880 | |||
881 | if (pwrap_is_mt8135(wrp)) { | ||
882 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
883 | "pwrap-bridge"); | ||
884 | wrp->bridge_base = devm_ioremap_resource(wrp->dev, res); | ||
885 | if (IS_ERR(wrp->bridge_base)) | ||
886 | return PTR_ERR(wrp->bridge_base); | ||
887 | |||
888 | wrp->rstc_bridge = devm_reset_control_get(wrp->dev, "pwrap-bridge"); | ||
889 | if (IS_ERR(wrp->rstc_bridge)) { | ||
890 | ret = PTR_ERR(wrp->rstc_bridge); | ||
891 | dev_dbg(wrp->dev, "cannot get pwrap-bridge reset: %d\n", ret); | ||
892 | return ret; | ||
893 | } | ||
894 | } | ||
895 | |||
896 | wrp->clk_spi = devm_clk_get(wrp->dev, "spi"); | ||
897 | if (IS_ERR(wrp->clk_spi)) { | ||
898 | dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_spi)); | ||
899 | return PTR_ERR(wrp->clk_spi); | ||
900 | } | ||
901 | |||
902 | wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap"); | ||
903 | if (IS_ERR(wrp->clk_wrap)) { | ||
904 | dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_wrap)); | ||
905 | return PTR_ERR(wrp->clk_wrap); | ||
906 | } | ||
907 | |||
908 | ret = clk_prepare_enable(wrp->clk_spi); | ||
909 | if (ret) | ||
910 | return ret; | ||
911 | |||
912 | ret = clk_prepare_enable(wrp->clk_wrap); | ||
913 | if (ret) | ||
914 | goto err_out1; | ||
915 | |||
916 | /* Enable internal dynamic clock */ | ||
917 | pwrap_writel(wrp, 1, PWRAP_DCM_EN); | ||
918 | pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); | ||
919 | |||
920 | /* | ||
921 | * The PMIC could already be initialized by the bootloader. | ||
922 | * Skip initialization here in this case. | ||
923 | */ | ||
924 | if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) { | ||
925 | ret = pwrap_init(wrp); | ||
926 | if (ret) { | ||
927 | dev_dbg(wrp->dev, "init failed with %d\n", ret); | ||
928 | goto err_out2; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) { | ||
933 | dev_dbg(wrp->dev, "initialization isn't finished\n"); | ||
934 | return -ENODEV; | ||
935 | } | ||
936 | |||
937 | irq = platform_get_irq(pdev, 0); | ||
938 | ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, | ||
939 | "mt-pmic-pwrap", wrp); | ||
940 | if (ret) | ||
941 | goto err_out2; | ||
942 | |||
943 | wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config); | ||
944 | if (IS_ERR(wrp->regmap)) | ||
945 | return PTR_ERR(wrp->regmap); | ||
946 | |||
947 | ret = of_platform_populate(np, NULL, NULL, wrp->dev); | ||
948 | if (ret) { | ||
949 | dev_dbg(wrp->dev, "failed to create child devices at %s\n", | ||
950 | np->full_name); | ||
951 | goto err_out2; | ||
952 | } | ||
953 | |||
954 | return 0; | ||
955 | |||
956 | err_out2: | ||
957 | clk_disable_unprepare(wrp->clk_wrap); | ||
958 | err_out1: | ||
959 | clk_disable_unprepare(wrp->clk_spi); | ||
960 | |||
961 | return ret; | ||
962 | } | ||
963 | |||
964 | static struct platform_driver pwrap_drv = { | ||
965 | .driver = { | ||
966 | .name = "mt-pmic-pwrap", | ||
967 | .owner = THIS_MODULE, | ||
968 | .of_match_table = of_match_ptr(of_pwrap_match_tbl), | ||
969 | }, | ||
970 | .probe = pwrap_probe, | ||
971 | }; | ||
972 | |||
973 | module_platform_driver(pwrap_drv); | ||
974 | |||
975 | MODULE_AUTHOR("Flora Fu, MediaTek"); | ||
976 | MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver"); | ||
977 | MODULE_LICENSE("GPL v2"); | ||