File Index
Files and directories
Sign in
FILE

gs101-pmu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/soc/samsung/gs101-pmu.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright 2025 Linaro Ltd.
  4 *
  5 * GS101 PMU (Power Management Unit) support
  6 */
  7
  8#include <linux/arm-smccc.h>
  9#include <linux/array_size.h>
 10#include <linux/soc/samsung/exynos-pmu.h>
 11#include <linux/soc/samsung/exynos-regs-pmu.h>
 12#include <linux/regmap.h>
 13
 14#include "exynos-pmu.h"
 15
 16#define PMUALIVE_MASK			GENMASK(13, 0)
 17#define TENSOR_SET_BITS			(BIT(15) | BIT(14))
 18#define TENSOR_CLR_BITS			BIT(15)
 19#define TENSOR_SMC_PMU_SEC_REG		0x82000504
 20#define TENSOR_PMUREG_READ		0
 21#define TENSOR_PMUREG_WRITE		1
 22#define TENSOR_PMUREG_RMW		2
 23
 24static const struct regmap_range gs101_pmu_registers[] = {
 25	regmap_reg_range(GS101_OM_STAT, GS101_SYSTEM_INFO),
 26	regmap_reg_range(GS101_IDLE_IP(0), GS101_IDLE_IP_MASK(3)),
 27	regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(0),
 28			 GS101_PPMPURAM_INFORM_SCL_CH(3)),
 29	regmap_reg_range(GS101_INFORM0, GS101_SYSIP_DAT(0)),
 30	/* skip SYSIP_DAT1 SYSIP_DAT2 */
 31	regmap_reg_range(GS101_SYSIP_DAT(3), GS101_PWR_HOLD_SW_TRIP),
 32	regmap_reg_range(GS101_GSA_INFORM(0), GS101_GSA_INFORM(1)),
 33	regmap_reg_range(GS101_INFORM4, GS101_IROM_INFORM),
 34	regmap_reg_range(GS101_IROM_CPU_INFORM(0), GS101_IROM_CPU_INFORM(7)),
 35	regmap_reg_range(GS101_PMU_SPARE(0), GS101_PMU_SPARE(3)),
 36	/* skip most IROM_xxx registers */
 37	regmap_reg_range(GS101_DREX_CALIBRATION(0), GS101_DREX_CALIBRATION(7)),
 38
 39#define CLUSTER_CPU_RANGE(cl, cpu)					\
 40	regmap_reg_range(GS101_CLUSTER_CPU_CONFIGURATION(cl, cpu),	\
 41			 GS101_CLUSTER_CPU_OPTION(cl, cpu)),		\
 42	regmap_reg_range(GS101_CLUSTER_CPU_OUT(cl, cpu),		\
 43			 GS101_CLUSTER_CPU_IN(cl, cpu)),		\
 44	regmap_reg_range(GS101_CLUSTER_CPU_INT_IN(cl, cpu),		\
 45			 GS101_CLUSTER_CPU_INT_DIR(cl, cpu))
 46
 47	/* cluster 0..2 and cpu 0..4 or 0..1 */
 48	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 0),
 49	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 1),
 50	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 2),
 51	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 3),
 52	CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 0),
 53	CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 1),
 54	CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 0),
 55	CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 1),
 56#undef CLUSTER_CPU_RANGE
 57
 58#define CLUSTER_NONCPU_RANGE(cl)					\
 59	regmap_reg_range(GS101_CLUSTER_NONCPU_CONFIGURATION(cl),	\
 60			 GS101_CLUSTER_NONCPU_OPTION(cl)),		\
 61	regmap_reg_range(GS101_CLUSTER_NONCPU_OUT(cl),			\
 62			 GS101_CLUSTER_NONCPU_IN(cl)),			\
 63	regmap_reg_range(GS101_CLUSTER_NONCPU_INT_IN(cl),		\
 64			 GS101_CLUSTER_NONCPU_INT_DIR(cl)),		\
 65	regmap_reg_range(GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_OUT(cl),	\
 66			 GS101_CLUSTER_NONCPU_DUALRAIL_POS_OUT(cl)),	\
 67	regmap_reg_range(GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl),	\
 68			 GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl))
 69
 70	CLUSTER_NONCPU_RANGE(0),
 71	regmap_reg_range(GS101_CLUSTER0_NONCPU_DSU_PCH,
 72			 GS101_CLUSTER0_NONCPU_DSU_PCH),
 73	CLUSTER_NONCPU_RANGE(1),
 74	CLUSTER_NONCPU_RANGE(2),
 75#undef CLUSTER_NONCPU_RANGE
 76
 77#define SUBBLK_RANGE(blk)						\
 78	regmap_reg_range(GS101_SUBBLK_CONFIGURATION(blk),		\
 79			 GS101_SUBBLK_CTRL(blk)),			\
 80	regmap_reg_range(GS101_SUBBLK_OUT(blk), GS101_SUBBLK_IN(blk)),	\
 81	regmap_reg_range(GS101_SUBBLK_INT_IN(blk),			\
 82			 GS101_SUBBLK_INT_DIR(blk)),			\
 83	regmap_reg_range(GS101_SUBBLK_MEMORY_OUT(blk),			\
 84			 GS101_SUBBLK_MEMORY_IN(blk))
 85
 86	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ALIVE),
 87	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_AOC),
 88	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_APM),
 89	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CMU),
 90	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS0),
 91	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS1),
 92	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS2),
 93	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CORE),
 94	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EH),
 95	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL0),
 96	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL1),
 97	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL2),
 98	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3D),
 99	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_CPUCL0),
100	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_G3D),
101	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI0),
102	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI1),
103	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI2),
104	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DPU),
105	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DISP),
106	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G2D),
107	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MFC),
108	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CSIS),
109	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PDP),
110	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DNS),
111	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3AA),
112	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_IPP),
113	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ITP),
114	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MCSC),
115	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_GDC),
116	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TNR),
117	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BO),
118	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TPU),
119	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF0),
120	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF1),
121	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF2),
122	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF3),
123	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MISC),
124	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC0),
125	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC1),
126	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_S2D),
127#undef SUBBLK_RANGE
128
129#define SUBBLK_CPU_RANGE(blk)						\
130	regmap_reg_range(GS101_SUBBLK_CPU_CONFIGURATION(blk),		\
131			 GS101_SUBBLK_CPU_OPTION(blk)),			\
132	regmap_reg_range(GS101_SUBBLK_CPU_OUT(blk),			\
133			 GS101_SUBBLK_CPU_IN(blk)),			\
134	regmap_reg_range(GS101_SUBBLK_CPU_INT_IN(blk),			\
135			 GS101_SUBBLK_CPU_INT_DIR(blk))
136
137	SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_APM),
138	SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_DBGCORE),
139	SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_SSS),
140#undef SUBBLK_CPU_RANGE
141
142	regmap_reg_range(GS101_MIF_CONFIGURATION, GS101_MIF_CTRL),
143	regmap_reg_range(GS101_MIF_OUT, GS101_MIF_IN),
144	regmap_reg_range(GS101_MIF_INT_IN, GS101_MIF_INT_DIR),
145	regmap_reg_range(GS101_TOP_CONFIGURATION, GS101_TOP_OPTION),
146	regmap_reg_range(GS101_TOP_OUT, GS101_TOP_IN),
147	regmap_reg_range(GS101_TOP_INT_IN, GS101_WAKEUP2_STAT),
148	regmap_reg_range(GS101_WAKEUP2_INT_IN, GS101_WAKEUP2_INT_DIR),
149	regmap_reg_range(GS101_SYSTEM_CONFIGURATION, GS101_USER_DEFINED_OUT),
150	regmap_reg_range(GS101_SYSTEM_OUT, GS101_SYSTEM_IN),
151	regmap_reg_range(GS101_SYSTEM_INT_IN, GS101_EINT_WAKEUP_MASK3),
152	regmap_reg_range(GS101_USER_DEFINED_INT_IN, GS101_SCAN2DRAM_INT_DIR),
153	/* skip HCU_START */
154	regmap_reg_range(GS101_CUSTOM_OUT, GS101_CUSTOM_IN),
155	regmap_reg_range(GS101_CUSTOM_INT_IN, GS101_CUSTOM_INT_DIR),
156	regmap_reg_range(GS101_ACK_LAST_CPU, GS101_HCU_R(3)),
157	regmap_reg_range(GS101_HCU_SP, GS101_HCU_PC),
158	/* skip PMU_RAM_CTRL */
159	regmap_reg_range(GS101_APM_HCU_CTRL, GS101_APM_HCU_CTRL),
160	regmap_reg_range(GS101_APM_NMI_ENABLE, GS101_RST_STAT_PMU),
161	regmap_reg_range(GS101_HPM_INT_IN, GS101_BOOT_STAT),
162	regmap_reg_range(GS101_PMLINK_OUT, GS101_PMLINK_AOC_CTRL),
163	regmap_reg_range(GS101_TCXO_BUF_CTRL, GS101_ADD_CTRL),
164	regmap_reg_range(GS101_HCU_TIMEOUT_RESET, GS101_HCU_TIMEOUT_SCAN2DRAM),
165	regmap_reg_range(GS101_TIMER(0), GS101_TIMER(3)),
166	regmap_reg_range(GS101_PPC_MIF(0), GS101_PPC_EH),
167	/* PPC_OFFSET, skip PPC_CPUCL1_0 PPC_CPUCL1_1 */
168	regmap_reg_range(GS101_EXT_REGULATOR_MIF_DURATION, GS101_TCXO_DURATION),
169	regmap_reg_range(GS101_BURNIN_CTRL, GS101_TMU_SUB_TRIP),
170	regmap_reg_range(GS101_MEMORY_CEN, GS101_MEMORY_SMX_FEEDBACK),
171	regmap_reg_range(GS101_SLC_PCH_CHANNEL, GS101_SLC_PCH_CB),
172	regmap_reg_range(GS101_FORCE_NOMC, GS101_FORCE_NOMC),
173	regmap_reg_range(GS101_FORCE_BOOST, GS101_PMLINK_SLC_BUSY),
174	regmap_reg_range(GS101_BOOTSYNC_OUT, GS101_CTRL_SECJTAG_ALIVE),
175	regmap_reg_range(GS101_CTRL_DIV_PLL_ALV_DIVLOW, GS101_CTRL_CLKDIV__CLKRTC),
176	regmap_reg_range(GS101_CTRL_SOC32K, GS101_CTRL_SBU_SW_EN),
177	regmap_reg_range(GS101_PAD_CTRL_CLKOUT0, GS101_PAD_CTRL_WRESETO_n),
178	regmap_reg_range(GS101_PHY_CTRL_USB20, GS101_PHY_CTRL_UFS),
179};
180
181static const struct regmap_range gs101_pmu_ro_registers[] = {
182	regmap_reg_range(GS101_OM_STAT, GS101_VERSION),
183	regmap_reg_range(GS101_OTP_STATUS, GS101_OTP_STATUS),
184
185	regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(0),
186			 GS101_PPMPURAM_STATE_SLC_CH(0)),
187	regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(1),
188			 GS101_PPMPURAM_STATE_SLC_CH(1)),
189	regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(2),
190			 GS101_PPMPURAM_STATE_SLC_CH(2)),
191	regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(3),
192			 GS101_PPMPURAM_STATE_SLC_CH(3)),
193
194#define CLUSTER_CPU_RANGE(cl, cpu)					\
195	regmap_reg_range(GS101_CLUSTER_CPU_IN(cl, cpu),			\
196			 GS101_CLUSTER_CPU_IN(cl, cpu)),		\
197	regmap_reg_range(GS101_CLUSTER_CPU_INT_IN(cl, cpu),		\
198			 GS101_CLUSTER_CPU_INT_IN(cl, cpu))
199
200	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 0),
201	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 1),
202	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 2),
203	CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 3),
204	CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 0),
205	CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 1),
206	CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 0),
207	CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 1),
208#undef CLUSTER_CPU_RANGE
209
210#define CLUSTER_NONCPU_RANGE(cl)					\
211	regmap_reg_range(GS101_CLUSTER_NONCPU_IN(cl),			\
212			 GS101_CLUSTER_NONCPU_IN(cl)),			\
213	regmap_reg_range(GS101_CLUSTER_NONCPU_INT_IN(cl),		\
214			 GS101_CLUSTER_NONCPU_INT_IN(cl)),		\
215	regmap_reg_range(GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl),	\
216			 GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl))
217
218	CLUSTER_NONCPU_RANGE(0),
219	CLUSTER_NONCPU_RANGE(1),
220	CLUSTER_NONCPU_RANGE(2),
221	regmap_reg_range(GS101_CLUSTER_NONCPU_INT_EN(2),
222			 GS101_CLUSTER_NONCPU_INT_DIR(2)),
223#undef CLUSTER_NONCPU_RANGE
224
225#define SUBBLK_RANGE(blk)						\
226	regmap_reg_range(GS101_SUBBLK_IN(blk), GS101_SUBBLK_IN(blk)),	\
227	regmap_reg_range(GS101_SUBBLK_INT_IN(blk),			\
228			 GS101_SUBBLK_INT_IN(blk)),			\
229	regmap_reg_range(GS101_SUBBLK_MEMORY_IN(blk),			\
230			 GS101_SUBBLK_MEMORY_IN(blk))
231
232	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ALIVE),
233	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_AOC),
234	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_APM),
235	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CMU),
236	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS0),
237	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS1),
238	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS2),
239	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CORE),
240	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EH),
241	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL0),
242	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL1),
243	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL2),
244	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3D),
245	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_CPUCL0),
246	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_G3D),
247	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI0),
248	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI1),
249	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI2),
250	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DPU),
251	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DISP),
252	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G2D),
253	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MFC),
254	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CSIS),
255	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PDP),
256	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DNS),
257	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3AA),
258	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_IPP),
259	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ITP),
260	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MCSC),
261	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_GDC),
262	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TNR),
263	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BO),
264	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TPU),
265	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF0),
266	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF1),
267	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF2),
268	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF3),
269	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MISC),
270	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC0),
271	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC1),
272	SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_S2D),
273#undef SUBBLK_RANGE
274
275#define SUBBLK_CPU_RANGE(blk)						\
276	regmap_reg_range(GS101_SUBBLK_CPU_IN(blk),			\
277			 GS101_SUBBLK_CPU_IN(blk)),			\
278	regmap_reg_range(GS101_SUBBLK_CPU_INT_IN(blk),			\
279			 GS101_SUBBLK_CPU_INT_IN(blk))
280
281	SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_APM),
282	SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_DBGCORE),
283	SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_SSS),
284#undef SUBBLK_CPU_RANGE
285
286	regmap_reg_range(GS101_MIF_CONFIGURATION, GS101_MIF_CONFIGURATION),
287	regmap_reg_range(GS101_MIF_IN, GS101_MIF_IN),
288	regmap_reg_range(GS101_MIF_INT_IN, GS101_MIF_INT_IN),
289	regmap_reg_range(GS101_TOP_IN, GS101_TOP_IN),
290	regmap_reg_range(GS101_TOP_INT_IN, GS101_TOP_INT_IN),
291	regmap_reg_range(GS101_WAKEUP2_INT_IN, GS101_WAKEUP2_INT_IN),
292	regmap_reg_range(GS101_SYSTEM_IN, GS101_SYSTEM_IN),
293	regmap_reg_range(GS101_SYSTEM_INT_IN, GS101_SYSTEM_INT_IN),
294	regmap_reg_range(GS101_EINT_INT_IN, GS101_EINT_INT_IN),
295	regmap_reg_range(GS101_EINT2_INT_IN, GS101_EINT2_INT_IN),
296	regmap_reg_range(GS101_EINT3_INT_IN, GS101_EINT3_INT_IN),
297	regmap_reg_range(GS101_USER_DEFINED_INT_IN, GS101_USER_DEFINED_INT_IN),
298	regmap_reg_range(GS101_SCAN2DRAM_INT_IN, GS101_SCAN2DRAM_INT_IN),
299	regmap_reg_range(GS101_CUSTOM_IN, GS101_CUSTOM_IN),
300	regmap_reg_range(GS101_CUSTOM_INT_IN, GS101_CUSTOM_INT_IN),
301	regmap_reg_range(GS101_HCU_R(0), GS101_HCU_R(3)),
302	regmap_reg_range(GS101_HCU_SP, GS101_HCU_PC),
303	regmap_reg_range(GS101_NMI_SRC_IN, GS101_NMI_SRC_IN),
304	regmap_reg_range(GS101_HPM_INT_IN, GS101_HPM_INT_IN),
305	regmap_reg_range(GS101_MEMORY_PGEN_FEEDBACK, GS101_MEMORY_PGEN_FEEDBACK),
306	regmap_reg_range(GS101_MEMORY_SMX_FEEDBACK, GS101_MEMORY_SMX_FEEDBACK),
307	regmap_reg_range(GS101_PMLINK_SLC_ACK, GS101_PMLINK_SLC_BUSY),
308	regmap_reg_range(GS101_BOOTSYNC_IN, GS101_BOOTSYNC_IN),
309	regmap_reg_range(GS101_SCAN_READY_IN, GS101_SCAN_READY_IN),
310	regmap_reg_range(GS101_CTRL_PLL_ALV_LOCK, GS101_CTRL_PLL_ALV_LOCK),
311};
312
313static const struct regmap_access_table gs101_pmu_rd_table = {
314	.yes_ranges = gs101_pmu_registers,
315	.n_yes_ranges = ARRAY_SIZE(gs101_pmu_registers),
316};
317
318static const struct regmap_access_table gs101_pmu_wr_table = {
319	.yes_ranges = gs101_pmu_registers,
320	.n_yes_ranges = ARRAY_SIZE(gs101_pmu_registers),
321	.no_ranges = gs101_pmu_ro_registers,
322	.n_no_ranges = ARRAY_SIZE(gs101_pmu_ro_registers),
323};
324
325const struct exynos_pmu_data gs101_pmu_data = {
326	.pmu_secure = true,
327	.pmu_cpuhp = true,
328	.rd_table = &gs101_pmu_rd_table,
329	.wr_table = &gs101_pmu_wr_table,
330};
331
332/*
333 * Tensor SoCs are configured so that PMU_ALIVE registers can only be written
334 * from EL3, but are still read accessible. As Linux needs to write some of
335 * these registers, the following functions are provided and exposed via
336 * regmap.
337 *
338 * Note: This SMC interface is known to be implemented on gs101 and derivative
339 * SoCs.
340 */
341
342/* Write to a protected PMU register. */
343int tensor_sec_reg_write(void *context, unsigned int reg, unsigned int val)
344{
345	struct arm_smccc_res res;
346	unsigned long pmu_base = (unsigned long)context;
347
348	arm_smccc_smc(TENSOR_SMC_PMU_SEC_REG, pmu_base + reg,
349		      TENSOR_PMUREG_WRITE, val, 0, 0, 0, 0, &res);
350
351	/* returns -EINVAL if access isn't allowed or 0 */
352	if (res.a0)
353		pr_warn("%s(): SMC failed: %d\n", __func__, (int)res.a0);
354
355	return (int)res.a0;
356}
357
358/* Read/Modify/Write a protected PMU register. */
359static int tensor_sec_reg_rmw(void *context, unsigned int reg,
360			      unsigned int mask, unsigned int val)
361{
362	struct arm_smccc_res res;
363	unsigned long pmu_base = (unsigned long)context;
364
365	arm_smccc_smc(TENSOR_SMC_PMU_SEC_REG, pmu_base + reg,
366		      TENSOR_PMUREG_RMW, mask, val, 0, 0, 0, &res);
367
368	/* returns -EINVAL if access isn't allowed or 0 */
369	if (res.a0)
370		pr_warn("%s(): SMC failed: %d\n", __func__, (int)res.a0);
371
372	return (int)res.a0;
373}
374
375/*
376 * Read a protected PMU register. All PMU registers can be read by Linux.
377 * Note: The SMC read register is not used, as only registers that can be
378 * written are readable via SMC.
379 */
380int tensor_sec_reg_read(void *context, unsigned int reg, unsigned int *val)
381{
382	*val = pmu_raw_readl(reg);
383	return 0;
384}
385
386/*
387 * For SoCs that have set/clear bit hardware this function can be used when
388 * the PMU register will be accessed by multiple masters.
389 *
390 * For example, to set bits 13:8 in PMU reg offset 0x3e80
391 * tensor_set_bits_atomic(ctx, 0x3e80, 0x3f00, 0x3f00);
392 *
393 * Set bit 8, and clear bits 13:9 PMU reg offset 0x3e80
394 * tensor_set_bits_atomic(0x3e80, 0x100, 0x3f00);
395 */
396static int tensor_set_bits_atomic(void *context, unsigned int offset, u32 val,
397				  u32 mask)
398{
399	int ret;
400	unsigned int i;
401
402	for (i = 0; i < 32; i++) {
403		if (!(mask & BIT(i)))
404			continue;
405
406		offset &= ~TENSOR_SET_BITS;
407
408		if (val & BIT(i))
409			offset |= TENSOR_SET_BITS;
410		else
411			offset |= TENSOR_CLR_BITS;
412
413		ret = tensor_sec_reg_write(context, offset, i);
414		if (ret)
415			return ret;
416	}
417	return 0;
418}
419
420static bool tensor_is_atomic(unsigned int reg)
421{
422	/*
423	 * Use atomic operations for PMU_ALIVE registers (offset 0~0x3FFF)
424	 * as the target registers can be accessed by multiple masters. SFRs
425	 * that don't support atomic are added to the switch statement below.
426	 */
427	if (reg > PMUALIVE_MASK)
428		return false;
429
430	switch (reg) {
431	case GS101_SYSIP_DAT(0):
432	case GS101_SYSTEM_CONFIGURATION:
433		return false;
434	default:
435		return true;
436	}
437}
438
439int tensor_sec_update_bits(void *context, unsigned int reg, unsigned int mask,
440			   unsigned int val)
441{
442	if (!tensor_is_atomic(reg))
443		return tensor_sec_reg_rmw(context, reg, mask, val);
444
445	return tensor_set_bits_atomic(context, reg, val, mask);
446}
~/ Read-only file preview.