xref: /openbmc/linux/drivers/soc/mediatek/mtk-infracfg.c (revision 16a624a9c81814cc2f1353eff2e502430c3fa79a)
1*16a624a9SSascha Hauer /*
2*16a624a9SSascha Hauer  * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
3*16a624a9SSascha Hauer  *
4*16a624a9SSascha Hauer  * This program is free software; you can redistribute it and/or modify
5*16a624a9SSascha Hauer  * it under the terms of the GNU General Public License version 2 as
6*16a624a9SSascha Hauer  * published by the Free Software Foundation.
7*16a624a9SSascha Hauer  *
8*16a624a9SSascha Hauer  * This program is distributed in the hope that it will be useful,
9*16a624a9SSascha Hauer  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10*16a624a9SSascha Hauer  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11*16a624a9SSascha Hauer  * GNU General Public License for more details.
12*16a624a9SSascha Hauer  */
13*16a624a9SSascha Hauer 
14*16a624a9SSascha Hauer #include <linux/export.h>
15*16a624a9SSascha Hauer #include <linux/jiffies.h>
16*16a624a9SSascha Hauer #include <linux/regmap.h>
17*16a624a9SSascha Hauer #include <linux/soc/mediatek/infracfg.h>
18*16a624a9SSascha Hauer #include <asm/processor.h>
19*16a624a9SSascha Hauer 
20*16a624a9SSascha Hauer #define INFRA_TOPAXI_PROTECTEN		0x0220
21*16a624a9SSascha Hauer #define INFRA_TOPAXI_PROTECTSTA1	0x0228
22*16a624a9SSascha Hauer 
23*16a624a9SSascha Hauer /**
24*16a624a9SSascha Hauer  * mtk_infracfg_set_bus_protection - enable bus protection
25*16a624a9SSascha Hauer  * @regmap: The infracfg regmap
26*16a624a9SSascha Hauer  * @mask: The mask containing the protection bits to be enabled.
27*16a624a9SSascha Hauer  *
28*16a624a9SSascha Hauer  * This function enables the bus protection bits for disabled power
29*16a624a9SSascha Hauer  * domains so that the system does not hang when some unit accesses the
30*16a624a9SSascha Hauer  * bus while in power down.
31*16a624a9SSascha Hauer  */
32*16a624a9SSascha Hauer int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
33*16a624a9SSascha Hauer {
34*16a624a9SSascha Hauer 	unsigned long expired;
35*16a624a9SSascha Hauer 	u32 val;
36*16a624a9SSascha Hauer 	int ret;
37*16a624a9SSascha Hauer 
38*16a624a9SSascha Hauer 	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
39*16a624a9SSascha Hauer 
40*16a624a9SSascha Hauer 	expired = jiffies + HZ;
41*16a624a9SSascha Hauer 
42*16a624a9SSascha Hauer 	while (1) {
43*16a624a9SSascha Hauer 		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
44*16a624a9SSascha Hauer 		if (ret)
45*16a624a9SSascha Hauer 			return ret;
46*16a624a9SSascha Hauer 
47*16a624a9SSascha Hauer 		if ((val & mask) == mask)
48*16a624a9SSascha Hauer 			break;
49*16a624a9SSascha Hauer 
50*16a624a9SSascha Hauer 		cpu_relax();
51*16a624a9SSascha Hauer 		if (time_after(jiffies, expired))
52*16a624a9SSascha Hauer 			return -EIO;
53*16a624a9SSascha Hauer 	}
54*16a624a9SSascha Hauer 
55*16a624a9SSascha Hauer 	return 0;
56*16a624a9SSascha Hauer }
57*16a624a9SSascha Hauer 
58*16a624a9SSascha Hauer /**
59*16a624a9SSascha Hauer  * mtk_infracfg_clear_bus_protection - disable bus protection
60*16a624a9SSascha Hauer  * @regmap: The infracfg regmap
61*16a624a9SSascha Hauer  * @mask: The mask containing the protection bits to be disabled.
62*16a624a9SSascha Hauer  *
63*16a624a9SSascha Hauer  * This function disables the bus protection bits previously enabled with
64*16a624a9SSascha Hauer  * mtk_infracfg_set_bus_protection.
65*16a624a9SSascha Hauer  */
66*16a624a9SSascha Hauer int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
67*16a624a9SSascha Hauer {
68*16a624a9SSascha Hauer 	unsigned long expired;
69*16a624a9SSascha Hauer 	int ret;
70*16a624a9SSascha Hauer 
71*16a624a9SSascha Hauer 	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
72*16a624a9SSascha Hauer 
73*16a624a9SSascha Hauer 	expired = jiffies + HZ;
74*16a624a9SSascha Hauer 
75*16a624a9SSascha Hauer 	while (1) {
76*16a624a9SSascha Hauer 		u32 val;
77*16a624a9SSascha Hauer 
78*16a624a9SSascha Hauer 		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
79*16a624a9SSascha Hauer 		if (ret)
80*16a624a9SSascha Hauer 			return ret;
81*16a624a9SSascha Hauer 
82*16a624a9SSascha Hauer 		if (!(val & mask))
83*16a624a9SSascha Hauer 			break;
84*16a624a9SSascha Hauer 
85*16a624a9SSascha Hauer 		cpu_relax();
86*16a624a9SSascha Hauer 		if (time_after(jiffies, expired))
87*16a624a9SSascha Hauer 			return -EIO;
88*16a624a9SSascha Hauer 	}
89*16a624a9SSascha Hauer 
90*16a624a9SSascha Hauer 	return 0;
91*16a624a9SSascha Hauer }
92