xref: /OK3568_Linux_fs/kernel/drivers/soc/mediatek/mtk-infracfg.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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