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