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 MTK_POLL_DELAY_US 10 21 #define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ)) 22 23 #define INFRA_TOPAXI_PROTECTEN 0x0220 24 #define INFRA_TOPAXI_PROTECTSTA1 0x0228 25 #define INFRA_TOPAXI_PROTECTEN_SET 0x0260 26 #define INFRA_TOPAXI_PROTECTEN_CLR 0x0264 27 28 /** 29 * mtk_infracfg_set_bus_protection - enable bus protection 30 * @regmap: The infracfg regmap 31 * @mask: The mask containing the protection bits to be enabled. 32 * @reg_update: The boolean flag determines to set the protection bits 33 * by regmap_update_bits with enable register(PROTECTEN) or 34 * by regmap_write with set register(PROTECTEN_SET). 35 * 36 * This function enables the bus protection bits for disabled power 37 * domains so that the system does not hang when some unit accesses the 38 * bus while in power down. 39 */ 40 int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask, 41 bool reg_update) 42 { 43 u32 val; 44 int ret; 45 46 if (reg_update) 47 regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 48 mask); 49 else 50 regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask); 51 52 ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1, 53 val, (val & mask) == mask, 54 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 55 56 return ret; 57 } 58 59 /** 60 * mtk_infracfg_clear_bus_protection - disable bus protection 61 * @regmap: The infracfg regmap 62 * @mask: The mask containing the protection bits to be disabled. 63 * @reg_update: The boolean flag determines to clear the protection bits 64 * by regmap_update_bits with enable register(PROTECTEN) or 65 * by regmap_write with clear register(PROTECTEN_CLR). 66 * 67 * This function disables the bus protection bits previously enabled with 68 * mtk_infracfg_set_bus_protection. 69 */ 70 71 int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask, 72 bool reg_update) 73 { 74 int ret; 75 u32 val; 76 77 if (reg_update) 78 regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0); 79 else 80 regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask); 81 82 ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1, 83 val, !(val & mask), 84 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 85 86 return ret; 87 } 88