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