162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2018, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/spinlock.h>
762306a36Sopenharmony_ci#include <asm/barrier.h>
862306a36Sopenharmony_ci#include <asm/sysreg.h>
962306a36Sopenharmony_ci#include <soc/qcom/kryo-l2-accessors.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define L2CPUSRSELR_EL1         sys_reg(3, 3, 15, 0, 6)
1262306a36Sopenharmony_ci#define L2CPUSRDR_EL1           sys_reg(3, 3, 15, 0, 7)
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(l2_access_lock);
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/**
1762306a36Sopenharmony_ci * kryo_l2_set_indirect_reg() - write value to an L2 register
1862306a36Sopenharmony_ci * @reg: Address of L2 register.
1962306a36Sopenharmony_ci * @val: Value to be written to register.
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * Use architecturally required barriers for ordering between system register
2262306a36Sopenharmony_ci * accesses, and system registers with respect to device memory
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_civoid kryo_l2_set_indirect_reg(u64 reg, u64 val)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	unsigned long flags;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	raw_spin_lock_irqsave(&l2_access_lock, flags);
2962306a36Sopenharmony_ci	write_sysreg_s(reg, L2CPUSRSELR_EL1);
3062306a36Sopenharmony_ci	isb();
3162306a36Sopenharmony_ci	write_sysreg_s(val, L2CPUSRDR_EL1);
3262306a36Sopenharmony_ci	isb();
3362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ciEXPORT_SYMBOL(kryo_l2_set_indirect_reg);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/**
3862306a36Sopenharmony_ci * kryo_l2_get_indirect_reg() - read an L2 register value
3962306a36Sopenharmony_ci * @reg: Address of L2 register.
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * Use architecturally required barriers for ordering between system register
4262306a36Sopenharmony_ci * accesses, and system registers with respect to device memory
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_ciu64 kryo_l2_get_indirect_reg(u64 reg)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	u64 val;
4762306a36Sopenharmony_ci	unsigned long flags;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&l2_access_lock, flags);
5062306a36Sopenharmony_ci	write_sysreg_s(reg, L2CPUSRSELR_EL1);
5162306a36Sopenharmony_ci	isb();
5262306a36Sopenharmony_ci	val = read_sysreg_s(L2CPUSRDR_EL1);
5362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return val;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ciEXPORT_SYMBOL(kryo_l2_get_indirect_reg);
58