1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
4 */
5
6#include <linux/export.h>
7#include <linux/jiffies.h>
8#include <linux/regmap.h>
9#include <linux/soc/mediatek/infracfg.h>
10#include <asm/processor.h>
11
12#define MTK_POLL_DELAY_US   10
13#define MTK_POLL_TIMEOUT    (jiffies_to_usecs(HZ))
14
15#define INFRA_TOPAXI_PROTECTEN		0x0220
16#define INFRA_TOPAXI_PROTECTSTA1	0x0228
17#define INFRA_TOPAXI_PROTECTEN_SET	0x0260
18#define INFRA_TOPAXI_PROTECTEN_CLR	0x0264
19
20/**
21 * mtk_infracfg_set_bus_protection - enable bus protection
22 * @infracfg: The infracfg regmap
23 * @mask: The mask containing the protection bits to be enabled.
24 * @reg_update: The boolean flag determines to set the protection bits
25 *              by regmap_update_bits with enable register(PROTECTEN) or
26 *              by regmap_write with set register(PROTECTEN_SET).
27 *
28 * This function enables the bus protection bits for disabled power
29 * domains so that the system does not hang when some unit accesses the
30 * bus while in power down.
31 */
32int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
33		bool reg_update)
34{
35	u32 val;
36	int ret;
37
38	if (reg_update)
39		regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask,
40				mask);
41	else
42		regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
43
44	ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
45				       val, (val & mask) == mask,
46				       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
47
48	return ret;
49}
50
51/**
52 * mtk_infracfg_clear_bus_protection - disable bus protection
53 * @infracfg: The infracfg regmap
54 * @mask: The mask containing the protection bits to be disabled.
55 * @reg_update: The boolean flag determines to clear the protection bits
56 *              by regmap_update_bits with enable register(PROTECTEN) or
57 *              by regmap_write with clear register(PROTECTEN_CLR).
58 *
59 * This function disables the bus protection bits previously enabled with
60 * mtk_infracfg_set_bus_protection.
61 */
62
63int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
64		bool reg_update)
65{
66	int ret;
67	u32 val;
68
69	if (reg_update)
70		regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
71	else
72		regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask);
73
74	ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
75				       val, !(val & mask),
76				       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
77
78	return ret;
79}
80